链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1595
题目:
5 6 1 2 4 1 3 3 2 3 1 2 4 4 2 5 7 4 5 1 6 7 1 2 1 2 3 4 3 4 4 4 6 4 1 5 5 2 5 2 5 6 5 5 7 1 2 8 1 4 10 2 3 9 2 4 10 2 5 1 3 4 7 3 5 10
11 13 27
分析与总结:
1. 最直接的想法,就是枚举每一条给的路径,把这条路径“删掉",删掉可以把邻接矩阵对应的边赋值为INF,然后依次求最短路。
但是所有的边数太多了,有1000*999/2条, 不用想了肯定是超时的。
所以选择删哪些边是最重要的。
2. 只需要先求一次最短路,记录好路径,然后枚举删除这条路径上的边,再求最短路,所有最短路中最大的那个就是答案。这样最多就只需要删除n次就可以了。为什么只要枚举的是最短路上的边就行了呢?很简单,如果枚举的是其他边,那么将会毫无影响,再次进行最短路算法时,得出的还是和原来的最短路一样。记录路径的方法是在松弛的时候用一个数组pre记录。
代码:
#include<cstring> #include<cstdio> #include<iostream> #include<queue> #include<utility> using namespace std; typedef pair<int,int>pii; const int INF = 1000000000; const int VN = 1005; const int EN = VN*VN/2; int n, m; int d[VN]; int w[VN][VN]; int pre[VN]; bool inq[VN]; bool flag; void init(){ flag=true; memset(pre, -1, sizeof(pre)); for(int i=0; i<=n; ++i){ w[i][i] = INF; for(int j=i+1; j<=n; ++j) w[i][j] = w[j][i] = INF; } } void Dijkstra(int src){ int tmp_pre[VN]; memset(tmp_pre, -1, sizeof(tmp_pre)); memset(inq, 0, sizeof(inq)); for(int i=1; i<=n; ++i)d[i]=INF; d[src] = 0; priority_queue<pii,vector<pii>,greater<pii> >q; q.push(make_pair(d[src],src)); while(!q.empty()){ pii x=q.top(); q.pop(); int u=x.second; if(d[u]!=x.first) continue; for(int v=1; v<=n; ++v){ int tmp=d[u]+w[u][v]; if(w[u][v]!=INF && d[v]>tmp){ tmp_pre[v] = u; d[v] = tmp; q.push(make_pair(d[v],v)); } } } if(flag){ memcpy(pre, tmp_pre, sizeof(tmp_pre)); flag=false; } } int main(){ int u,v,c; while(~scanf("%d%d",&n,&m)){ init(); for(int i=0; i<m; ++i){ scanf("%d%d%d",&u,&v,&c); if(w[u][v]>c) w[u][v]=w[v][u]=c; } Dijkstra(1); int j=n, ans=-INF; while(pre[j]!=-1){ int cost = w[j][pre[j]]; //备份 w[j][pre[j]] = w[pre[j]][j] = INF; Dijkstra(1); if(d[n]!=INF && d[n]>ans)ans=d[n]; w[j][pre[j]] = w[pre[j]][j] = cost; j = pre[j]; } printf("%d\n", ans); } return 0; }
—— 生命的意义,在于赋予它意义。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)