Code[VS]1021 玛丽卡题解
题目传送门:http://codevs.cn/problem/1021/
题目描述 Description
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
输入描述 Input Description
第一行有两个用空格隔开的数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分钟内是就能通过。
输出描述 Output Description
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
样例输入 Sample Input
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
样例输出 Sample Output
27
分析
本题求解最短路线通过不堵车道路到达他所在城市所需的最长时间,不难想到,堵车的道路一定要在最短路上才有最大值,否则无论道路在哪都不会影响原来的值。
首先进行一遍SPFA,找出原图中的最短路,并记录路径。再枚举路径上的所有点,删去这条边,再SPFA。一遍遍查找,最终找到最大值。
注释&代码
1 #include "bits/stdc++.h" 2 3 using namespace std; 4 const int maxN = 210000 ; 5 const int INF = 1000000000; 6 struct Edge 7 { 8 int from , to , next , w ; 9 }e[ 5000010 ]; 10 11 int n,m,cnt,p[ maxN ],Dis[ maxN ]; 12 int In[ maxN ],pre[ maxN ] ; 13 bool visited[ maxN ]; 14 15 void Add_edge(const int x,const int y,const int z) 16 { 17 e[ ++cnt ].to = y ; 18 e[ cnt ].next = p [ x ] ; 19 e[ cnt ].w = z ; 20 e[ cnt ].from = x ; 21 p[ x ] = cnt ; 22 return ; 23 } 24 25 void Spfa ( const int S ) 26 { 27 int i , t , temp ; 28 queue <int> Q; 29 memset ( visited , 0 , sizeof ( visited ) ) ; 30 memset ( Dis , 0x3f , sizeof ( Dis ) ) ; 31 memset ( In , 0 , sizeof ( In ) ) ; 32 33 Q.push( S ) ; 34 visited[ S ] = true; 35 Dis[ S ] = 0 ; 36 37 while(!Q.empty())//SPFA找最短路 38 { 39 t=Q.front();Q.pop();visited[t]=false; 40 for(i=p[t];i;i=e[i].next) 41 { 42 temp=e[i].to; 43 if(Dis[temp]>Dis[t]+e[i].w) 44 { 45 Dis[temp]=Dis[t]+e[i].w; 46 pre [ temp ] = i ; //记录路径 47 if(!visited[temp]) 48 { 49 Q.push(temp); 50 visited[temp]=true; 51 if(++In[temp]>n)return ; 52 } 53 54 } 55 } 56 } 57 } 58 59 void work ( int x ) 60 { 61 int i,t,temp; 62 queue<int> Q; 63 memset(visited,0,sizeof(visited)); 64 memset(Dis,0x3f,sizeof(Dis)); 65 memset(In,0,sizeof(In)); 66 int S = 1 , haha ; 67 68 haha = e[ x ].w , e[ x ].w = INF ;//删边 69 Q.push( S ); 70 visited[ S ] = true; 71 Dis[ S ] = 0 ; 72 73 while( !Q.empty ( ) )//SPFA 74 { 75 t=Q.front ( ) ;Q.pop ( ) ;visited[ t ] = false ; 76 for( i=p[t] ; i ; i = e[ i ].next ) 77 { 78 temp = e[ i ].to; 79 if(Dis[ temp ] > Dis[ t ] + e[ i ].w ) 80 { 81 Dis[ temp ] = Dis[ t ]+e[ i ].w ; 82 if( !visited[ temp ] ) 83 { 84 Q.push ( temp ) ; 85 visited[ temp ] = true ; 86 if( ++In[ temp ] > n )return ; 87 } 88 } 89 } 90 } 91 e[ x ].w = haha ;//恢复 92 } 93 94 int main() 95 { 96 int x , y , _ ; 97 98 scanf ( "%d%d" , &n , &m ) ; 99 for(int i=1 ; i<=m ; ++i ) 100 { 101 scanf ( "%d%d%d" , &x , &y , &_ ) ; 102 Add_edge( x , y , _ ) ; 103 Add_edge( y , x , _ ) ; 104 } 105 106 Spfa( 1 ) ; 107 int ans = Dis [ n ] ; 108 109 for ( int i=n ; i!=1 ; i =e[ pre[ i ] ].from ){ 110 work ( pre[ i ] ) ; 111 ans = max ( ans , Dis[ n ] ) ;//比较最大值 112 } 113 printf ( "%d" , ans ) ; 114 return 0 ; 115 }
(完)