链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1595
题目:
分析与总结:
1. 最直接的想法,就是枚举每一条给的路径,把这条路径“删掉",删掉可以把邻接矩阵对应的边赋值为INF,然后依次求最短路。
但是所有的边数太多了,有1000*999/2条, 不用想了肯定是超时的。
所以选择删哪些边是最重要的。
2. 只需要先求一次最短路,记录好路径,然后枚举删除这条路径上的边,再求最短路,所有最短路中最大的那个就是答案。这样最多就只需要删除n次就可以了。为什么只要枚举的是最短路上的边就行了呢?很简单,如果枚举的是其他边,那么将会毫无影响,再次进行最短路算法时,得出的还是和原来的最短路一样。记录路径的方法是在松弛的时候用一个数组pre记录。
代码:
#include
#include
#include
#include
#include
using namespace std;
typedef pairpii;
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,greater >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; ic) 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;
}
—— 生命的意义,在于赋予它意义。