标签:
【题目大意】
给出一张无向图,求出从源点到终点的次短边。
【思路】
先来谈谈Dijkstra的优化。对于每次寻找到当前为访问过的点中距离最短的那一个,运用优先队列进行优化,避免全部扫描,每更新一个点的最短距离就加入优先队列。有人会问,一个点如果已经处理完成了,那它还留在队列中怎么办?我们放入队列时将一个点那时的顶点编号和最短距离进行打包,如果取出该点时,它当前的最短距离小于该点标记的最短距离,说明该点已经取到最短距离,不进行操作。或者直接用一个vis数组来记录某一个点是否已经取到最短距离;其次的优化是用邻接表存储与每一个点相连的所有边,方便处理。
这道题的做法和最短路径基本一致,唯一的不同点在于,在求出最短路径的情况下必须要保留下次短路径。对于Dijkstra判断中取出的每一个点,如果到它的最短距离大于当前该点的次短距离,则当前该点已经取到最短距离和次短距离,不进行操作,否则进行两次判断:如果小于最短边,则赋给最短变,并将最短边赋给次短边;或者如果大于最短变且小于次短边,则赋给次短边。两次完成之后均要加入队列。要注意几点:
(1)由于是一张无向图,读入的时候必须正向、逆向分为两条边存储,所以实际有向边的数量为r的两倍,数组绝对不能开小!我就因为这个错拿了90分,还检查了三个小时后找到测试数据才意识到的...
(2)初始化时,源点的短边初始化为0,源点的次短边必须初始化为INF,而不是0。比如下面这组数据:
4 2 1 2 100 2 4 200
答案应该是500,然而如果初始化为0则答案会输出700。因为500的结果是又1到2,在从2返回1,再到2,再到4,100+100+100+200=500得到的;如果次短边初始化为0,则次短路径不再返回源点,而是在2与4之间折返,会偏大。
(3)53行绝对不能直接赋值,而是要swap!因为最短边被修改后,它的值是要留给次短边的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<cstdlib> 6 using namespace std; 7 const int INF=0x7fffffff; 8 const int MAXN=100000+10; 9 struct Rec 10 { 11 int num,len; 12 bool operator < (const Rec &a) const 13 { 14 return len>a.len; 15 16 } 17 }; 18 int u[MAXN*2],v[MAXN*2],w[MAXN*2]; 19 20 int dis[MAXN/2],secondis[MAXN/2]; 21 22 int first[MAXN/2],next[MAXN*2]; 23 int n,r; 24 25 void dijkstra() 26 { 27 priority_queue<Rec> que; 28 29 for (int i=1;i<n;i++) 30 { 31 dis[i]=INF; 32 secondis[i]=INF; 33 } 34 dis[0]=0; 35 secondis[0]=INF; 36 37 Rec temp; 38 temp.len=0;temp.num=0; 39 que.push(temp); 40 41 while (!que.empty()) 42 { 43 Rec head=que.top(); 44 que.pop(); 45 if (head.len>secondis[head.num]) continue; 46 47 int k=first[head.num]; 48 while (k!=-1) 49 { 50 int d=head.len+w[k]; 51 if (dis[v[k]]>d) 52 { 53 swap(dis[v[k]],d); 54 temp.len=dis[v[k]];temp.num=v[k]; 55 que.push(temp); 56 57 } 58 if (dis[v[k]]<d && secondis[v[k]]>d) 59 { 60 secondis[v[k]]=d; 61 temp.len=secondis[v[k]];temp.num=v[k]; 62 que.push(temp); 63 64 } 65 k=next[k]; 66 } 67 } 68 } 69 70 int main() 71 { 72 scanf("%d%d",&n,&r); 73 74 memset(first,-1,sizeof(first)); 75 for (int i=0;i<r;i++) 76 { 77 scanf("%d%d%d",&u[i],&v[i],&w[i]); 78 u[i]--; 79 v[i]--; 80 next[i]=first[u[i]]; 81 first[u[i]]=i; 82 83 v[i+r]=u[i]; 84 u[i+r]=v[i]; 85 w[i+r]=w[i]; 86 next[i+r]=first[u[i+r]]; 87 first[u[i+r]]=i+r; 88 89 } 90 dijkstra(); 91 cout<<secondis[n-1]<<endl; 92 system("pause"); 93 return 0; 94 }
【dijkstra优化/次短路径】POJ3255-Roadblocks
标签:
原文地址:http://www.cnblogs.com/iiyiyi/p/4706182.html