POJ3255(Roadblocks)--次短路径
3228K | 485MS | G++ | 2453B |
根据题意和测试用例知道这是一个求次短路径的题目。次短路径,就是比最短路径长那么一丢丢的路径,而题中又是要求从一点到指定点的次短路径,果断Dijkstra。
R (1 ≤ R ≤ 100,000,N (1 ≤ N ≤ 5000) ,length D (1 ≤ D ≤ 5000),所以我用链式向前星方法存储,这个不知道的点这里(我转载别人的,讲的挺详细)。
用一个二维数组dist[MAXN][2],去记录i->j的最短路径和次短路径,第二维是0表示当期拿记录最短边,是1表示当前记录次短边。思路是这样,dist初始值为INF,当if(!vis[j][0] && dis[j][0] < MIN),即找到最短边,标记下来;如果 else if(!vis[j][1] && dis[j][1] < MIN),则是次短边,标记下来。所后进行松弛操作。。。。
1 /************************************************************************* 2 > File Name: poj3255.cpp 3 > Author: YeGuoSheng 4 > Description: 5 给定n个点和需要到达的点编号 6 问从1号点到目标点的次短路径 7 > Created Time: 2019年07月21日 星期日 16时40分46秒 8 ************************************************************************/ 9 10 #include<iostream> 11 #include<stdio.h> 12 #include<cstring> 13 #include<cmath> 14 #include<stack> 15 #include<map> 16 #include<set> 17 #include<list> 18 #include<queue> 19 #include<string> 20 #include<algorithm> 21 #include<iomanip> 22 #define INF 0x3f3f3f3f 23 #define MAXN 50010 24 25 struct node 26 { 27 int v; 28 int next; 29 int w; 30 }edges[MAXN<<2]; 31 32 int head[MAXN]; 33 int cnt; 34 int dis[MAXN][2];//dist [i][0]:1 最短路径 ,dist[i][1]次短路径 35 bool vis[MAXN][2];//vis[i][0]:1 表示到结点i的最短路径已找到,vis[i][1]表示到结点i的次短路径已找到 36 int n,m; 37 38 void add(int u,int v,int w)//链式向前星存储 39 { 40 edges[++cnt].v=v; 41 edges[cnt].w=w; 42 edges[cnt].next=head[u]; 43 head[u]=cnt; 44 } 45 46 void dijkstra(int s) 47 { 48 for(int i=0;i <= n;i++) 49 { 50 dis[i][0]=dis[i][1]= INF;//dist [i][0] 最短路径 ,dist[i][1]次短路径 51 vis[i][0]=vis[i][1]= 0; 52 } 53 dis[s][0] = 0; 54 for(int i = 1;i < n*2;i++) 55 { 56 int MIN = INF; 57 int k = 0; 58 int flag = 0; 59 for(int j = 1;j <= n;j++) 60 { 61 if(!vis[j][0] && dis[j][0] < MIN) 62 { 63 MIN=dis[j][0];//找到最小边 将点标记 64 k=j; 65 flag = 0; 66 } 67 else if(!vis[j][1] && dis[j][1] < MIN)//否则找到的就是次短边 68 { 69 MIN=dis[j][1]; 70 k=j; 71 flag = 1; 72 } 73 } 74 if(MIN == INF)break;//没找到 最短或次短路径 75 vis[k][flag]=1;//标记到结点k的最小边或次短边已经找到 76 for(int j= head[k];j!=-1;j=edges[j].next) 77 { 78 int v = edges[j].v;//第j条边的终点 79 int w = edges[j].w;//这条边的权重 80 if(MIN+w <= dis[v][0])//小于最短边,更新最短边,同时最短边变为次短边 81 { 82 dis[v][1] = dis[v][0];//既然dis[v][0]有更小的,那么我先把原来的赋值给dis[v][1] 83 dis[v][0] = MIN+w; 84 } 85 else if(MIN+w <= dis[v][1])//如果大于最短边,小于次短边,根新次短边 86 { 87 dis[v][1] = MIN+w; 88 } 89 } 90 } 91 } 92 int main() 93 { 94 memset(head,-1,sizeof(head)); 95 cnt = 0; 96 scanf("%d%d",&n,&m);// n:目标结点, m:边的数幂 97 for(int i=1;i<=m;i++) 98 { 99 int x,y,z; 100 scanf("%d%d%d",&x,&y,&z); 101 add(x,y,z); 102 add(y,x,z); 103 } 104 dijkstra(1); 105 printf("%d\n",dis[n][1]); 106 return 0; 107 }
----------------------------------------------------------------------------------------------------------------转载请说明出处----------------------------------------------------------------------------------------------------------------------
你要做一个不动声色的大人了。不准情绪化,不准偷偷想念,不准回头看。去过自己另外的生活。你要听话,不是所有的鱼都会生活在同一片海里。
————————村上春树