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 }
View Code

 

posted @ 2019-07-21 21:21  回忆酿的甜  阅读(1255)  评论(0编辑  收藏  举报
Live2D