您的位置:首页 > 其它

dijkstra模板+ 缩点-bupt新oj-187- Find the Fastest Server

2015-04-02 14:16 190 查看
先放一下dijkstra的模板。

不要问我为什么最短路这么基础的东西都要用模板!!!因为我图论弱啊!

typedef pair<int, int> P;

int V;
int d[SIZE_D];

void dijkstra(int s)
{
V = N;
priority_queue<P,vector<P>,greater<P> > que;
//fill(d,d + V, INF);
//为何楼上的fill没有用啊
memset(d,-1,sizeof(d));//第一次修改
d[s] = 0;
que.push(P(0,s));
while (!que.empty()){
P p = que.top();que.pop();
int ver = p.second;
if (d[ver] != -1 && d[ver] < p.first) continue;//第二次修改
for (int i = head[ver]; i != -1; i = pra[i].next){
int u = pra[i].to, cost = pra[i].w;
if (ser[u] != 0) continue;
if (d[u] == -1 || d[u] > d[ver] + cost){
d[u] = d[ver] + cost;
que.push(P(d[u],u));//第五次修改
}
}
}
}
//无法到达的点d是-1

题目链接:http://code.bupt.edu.cn/problem/p/187/

讲一下这道题目的题意

题意:有10^4个点,10^5条边,每条边有一个延时,告诉你10^3个服务站。给你10^4个查询点,问每个查询点到最快能到的服务站的延时是多少。注意:一共有40组样例!!!

解答:

1、我一开始用每输入一个服务站就bfs更新所有点的最小距离d【i】的方法,我算了复杂度是10^3 × 10^ 4 大约10的七次方,时限一秒可以过,但是有40组样例啊!10的8次方啊!

2、然后是用二分算一个距离,bfs看看在这个距离里面有没有服务站,有就跳出来,复杂度我不懂算啊!因为bfs随时可以跳出啊!但我觉得比方法一快啊!可是结果比方法一慢了一倍啊!

3、最后就是正解啦!

因为这道题里面,server没有区别,所以可以缩成一个点。这是一个好思路啊!

无差别的点可以缩成一个点啊!!!!!

然后跑一遍dijkstra。把这个超级点作为起点,记录d【i】,然后每次查询就是O(1)的了。

还可以用spfa一试,待会试试看,再来贴代码。

4、还有一件事情啊!那个样例输出是错的啊!!!

不过刚刚让田田把样例改对了。我应该早点跟他说的,刚刚交代码每次都交两遍,wa的次数要除以2了。不过现在的样例是对的了真是造福后人啊!

5、不知道为什么我用fill函数不能把数组变成INF.我查了一下http://www.cplusplus.com/reference/algorithm/fill/ 明明就是在头文件algorithm里面的啊!

粗心的傻逼错:

1、无向图啊!双向边啊!

2、图可能不连通啊!要输出-1啊!!!

3、变量居然打错了orz简直傻逼。。。

放一下dijkstra的代码

#include<bits/stdc++.h>
#define SIZE_D 20005
#define SIZE_B 500005
#define INF 0x3f3f3f3f
using namespace std;
int N,M;
int e,head[SIZE_D];
struct pp
{
int to,w,next;
}pra[SIZE_B];
void init()
{
e = 0;
memset(head,-1,sizeof(head));
}
int addedge(int x,int y,int z)
{
pra[e].to = y;
pra[e].w = z;
pra[e].next = head[x];
head[x] = e++;
}

bool ser[SIZE_D];

typedef pair<int, int> P;

int V;
int d[SIZE_D];

void dijkstra(int s)
{
V = N;
priority_queue<P,vector<P>,greater<P> > que;
//fill(d,d + V, INF);
//为何楼上的fill没有用啊
memset(d,-1,sizeof(d));//第一次修改
d[s] = 0;
que.push(P(0,s));
while (!que.empty()){
P p = que.top();que.pop();
int ver = p.second;
if (d[ver] != -1 && d[ver] < p.first) continue;//第二次修改
for (int i = head[ver]; i != -1; i = pra[i].next){
int u = pra[i].to, cost = pra[i].w;
if (ser[u] != 0) continue;
if (d[u] == -1 || d[u] > d[ver] + cost){
d[u] = d[ver] + cost;
que.push(P(d[u],u));//第五次修改
}
}
}
}
//无法到达的点d是-1

void copyc(int oldd,int newd)
{
for (int i = head[oldd]; i != -1; i = pra[i].next){
addedge(newd,pra[i].to,pra[i].w);
addedge(pra[i].to,newd,pra[i].w);//第三次修改
}
}
int main()
{
//freopen("input.txt","r",stdin);
int T;
scanf("%d",&T);
while (T--){
init();
scanf("%d %d",&N,&M);
for (int i = 0; i < M; i++){
int temp1,temp2,temp3;
scanf("%d %d %d",&temp1,&temp2,&temp3);
addedge(temp1,temp2,temp3);
addedge(temp2,temp1,temp3);
}
int k;
scanf("%d",&k);
memset(ser,0, sizeof(ser));
int super;
for (int i = 1; i <= k; i++){
int tempv;
scanf("%d",&tempv);
ser[tempv] = 1;
if (i == 1)
super = tempv;
else
copyc(tempv,super);
}
dijkstra(super);
int Q;
scanf("%d",&Q);
for (int i = 0; i < Q; i++){
int tempq;
scanf("%d",&tempq);
if (ser[tempq] == 1 ){
puts("0");
}else{
printf("%d\n",d[tempq]);
}
}
puts("");
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dijkstra