1021 玛丽卡
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
27
------------------------------------------------------------------------------------------------------------------------------------
题意大概是说给你一个无向图和各边的边权,但图中有一条边是不能够走的,保证在去掉图中任意一条边后仍有路径能从1到N,求在这种情况下从1到N的所有最短路的最大值。
很明显要用最短路算法,这里用的SPFA,思路是先跑一遍SPFA,找出当图是完整的(即假定所有边都可以走)时的最短路径,并记录下来,然后再遮掉这条路径上的一边跑SPFA,到该路径上所有边都被遮掉过,就能得出所有最短路的最大值了,即答案。
为什么要先跑一遍SPFA找原图的最短路径?
因为只有在原图的最短路径上进行操作(即去掉一条边)才能对图的最短路径产生影响;如果每条边都去枚举遮掉的话就等着程序原地爆炸吧。
AC代码:
1 #include<stdio.h> 2 #include<string.h> 3 #define maxn 2333 4 int dis[maxn],n,m,pre[maxn],cnt,team[2333333],head,tail,ans,con,prep[maxn],sz[maxn]; 5 bool b[maxn],ep[666666],flag; 6 struct node{ 7 int to; 8 int next; 9 int w; 10 }; 11 node e[666666]; 12 int ins(int,int,int); 13 int spfa(); 14 int find(int); 15 int main(){ 16 flag=true; 17 memset(ep,0,sizeof(ep)); 18 scanf("%d %d",&n,&m); 19 cnt=0; 20 for(int i=1;i<=m;i++){ 21 int x,y,t; 22 scanf("%d %d %d",&x,&y,&t); 23 ins(x,y,t);//建图 24 } 25 ans=0; 26 spfa();//找原图最短路径并记录 27 flag=false; 28 con=0; 29 find(n);//转存最短路径 30 for(int i=1;i<=con;i+=2){ 31 ep[sz[i]]=1;ep[sz[i+1]]=1; 32 spfa(); 33 ep[sz[i]]=0;ep[sz[i+1]]=0; 34 if(ans<dis[n]) ans=dis[n]; 35 } 36 printf("%d",ans); 37 return 0; 38 } 39 int ins(int x,int y,int w){ 40 e[++cnt].to=y;e[cnt].w=w;e[cnt].next=pre[x];pre[x]=cnt; 41 e[++cnt].to=x;e[cnt].w=w;e[cnt].next=pre[y];pre[y]=cnt; 42 } 43 int spfa(){ 44 memset(b,0,sizeof(b)); 45 memset(team,0,sizeof(team)); 46 for(int i=1;i<=n;i++) dis[i]=1e9; 47 head=0;tail=1; 48 team[tail]=1;b[1]=true; 49 dis[1]=0; 50 do{ 51 int u; 52 head++;u=team[head]; 53 for(int i=pre[u];i;i=e[i].next){ 54 if(!ep[i]){ 55 if(dis[e[i].to]>dis[u]+e[i].w){ 56 dis[e[i].to]=dis[u]+e[i].w; 57 if(flag) prep[e[i].to]=i;//记录最短路径 58 if(!b[e[i].to]){ 59 tail++; 60 team[tail]=e[i].to; 61 b[e[i].to]=true; 62 } 63 } 64 } 65 } 66 b[u]=false; 67 }while(head<tail); 68 } 69 int find(int x){ 70 if(x!=1){ 71 con++;sz[con]=prep[x]; 72 con++; 73 if(prep[x]%2==0) sz[con]=prep[x]-1; 74 else sz[con]=prep[x]+1; 75 find(e[sz[con]].to); 76 } 77 }