题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3986
思路:先spfa求出最短路,然后枚举删除最短路上的边,每次删除一条边,就求一次最短路,然后去最大的那个就行了。。。可以重边的问题没考虑完善,wa了好多次啊!!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<vector> 5 using namespace std; 6 const int MAXN=1000+10; 7 const int inf=1<<30; 8 struct Node{ 9 int v,w,id; 10 }; 11 vector<Node>vet[MAXN]; 12 int path[MAXN]; 13 int dist[MAXN]; 14 bool visited[MAXN]; 15 bool mark[MAXN*50]; 16 int id[MAXN]; 17 int n,m; 18 bool tag; 19 20 void SPFA(int u){ 21 for(int i=1;i<=n;i++)dist[i]=inf; 22 dist[u]=0; 23 memset(visited,false,sizeof(visited)); 24 queue<int>Q; 25 Q.push(u); 26 while(!Q.empty()){ 27 int u=Q.front(); 28 Q.pop(); 29 visited[u]=false; 30 for(int i=0;i<vet[u].size();i++){ 31 int v=vet[u][i].v; 32 int w=vet[u][i].w; 33 int ID=vet[u][i].id; 34 if(mark[vet[u][i].id])continue; 35 if(dist[u]+w<dist[v]){ 36 dist[v]=dist[u]+w; 37 if(tag)path[v]=u,id[v]=ID;//这边只需第一次的时候记录路径就行了。。。 38 if(!visited[v]){ 39 Q.push(v); 40 visited[v]=true; 41 } 42 } 43 } 44 } 45 } 46 47 48 int main(){ 49 int _case; 50 scanf("%d",&_case); 51 while(_case--){ 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++)vet[i].clear(); 54 memset(path,-1,sizeof(path)); 55 memset(mark,false,sizeof(mark)); 56 //memset(id,0,sizeof(id)); 57 for(int i=1;i<=m;i++){ 58 int u,v,w; 59 scanf("%d%d%d",&u,&v,&w); 60 Node p1,p2; 61 p1.v=u,p2.v=v; 62 p1.w=p2.w=w; 63 p1.id=p2.id=i; //每次输的时候边的id是一样的 64 vet[u].push_back(p2); 65 vet[v].push_back(p1); 66 } 67 tag=true; 68 SPFA(1); 69 tag=false; 70 if(dist[n]==inf){ 71 printf("-1\n"); 72 continue; 73 } 74 int ans=0; 75 bool flag=true; 76 for(int u=n;u!=-1;u=path[u]){ 77 //由于有重边,故每次要找不同id的 78 mark[id[u]]=true; 79 SPFA(1); 80 mark[id[u]]=false; 81 if(dist[n]==inf){ 82 printf("-1\n"); 83 flag=false; 84 break; 85 } 86 ans=max(ans,dist[n]); 87 } 88 if(flag){ 89 printf("%d\n",ans); 90 } 91 } 92 return 0; 93 }