题意:
有一城市,这个城市有n个地点和m条连接他们的路,点的编号是从1到n,小X住在1,他想去n。
但是最近正在维修公路,也就是说这m条路有且只有一条是坏的,但是小X不知道是哪一条,一条很关键的路坏了路程就会增加很多,所以小X想知道从1到n *最*坏*情*况* 下的路程。你能帮助他吗?
Input
每组数据开头有一个N和M.1 ≤ N ≤ 1000, 1 ≤ M ≤ N*(N-1)/2. 代表点的数量和边的数量,小X在1,他想去n. 然后有M行,每行有三个数 X , Y , Z. 1 ≤ X,Y ≤ N, 1 ≤ Z ≤ 1000.代表X和Y之间有一条双向的公路,它的长度是Z.
Output
输出最坏情况下的路程。
Sample Input
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
Sample Output
11
13
27
思路:
题意只要求删除一条边,所以最容易想到的方法就是以次删除M条边的一条,然后求一次Dijkstra保留最大的距离。但是这种简单的暴力求解是一定会超时的。题意让我们找的是去掉一条边后的最短路的最大值,假设在不删除边的情况下能找到一条1到n最短路s1,而在删除一条边的情况下我们找到一条最短路s2。
s1唯一或不唯一对下面的的分析没有影响,假设s1唯一。
当删除的边不在s1的路径上,那么s2==s1,所以如果不是删除s1上的路径,我们所求的s2是没有意义的。所以应该删除s1上的边,做法应该是在不删除边的情况下求一次最短路并把路径保留下来,然后依次删除s1上的路径保留1到n的最大值就行了。
代码:
#define N 1010
#define mod 1000000007
#define PI 3.1415926
#define inf 0x3f3f3f3f
#define poor 1000
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m,a,b,c,flag;
int k[N][N],dis[N];
bool book[N];
int pre[N*100];
//pre[v]=u 在最短路中存在u->v这条边(1~>v是通过1~>u与u->v更新而来的)
int Dijkstra()
{
memset(book,0,sizeof(book));
for(int i=1; i<=n; i++)
dis[i]=k[1][i];
book[1]=1;
dis[1]=0;
for(int i=0; i<n; i++)
{
int minn=inf,u;
for(int j=1; j<=n; j++)
if(!book[j]&&dis[j]<minn)
{
minn=dis[j];
u=j;
}
if(minn==inf)break;
book[u]=1;
for(int v=1; v<=n; v++)
{
if(k[u][v]<inf)
{
if(dis[v]>k[u][v]+minn&&!book[v])
{
dis[v]=k[u][v]+minn;
if(!flag)pre[v]=u;//通过u->v这条边可以更新而来的
}
}
}
}
return dis[n];
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
flag=0;
fill(pre,pre+n,1);
//假设开始时所有边都与1相连,就是1->i(如果1->i没有直接相连dis[i]=inf)
for(int i=1; i<=n; i++)
{
k[i][i]=0;
for(int j=i+1; j<=n; j++)
k[i][j]=k[j][i]=inf;
}
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
if(k[a][b]>c)
k[a][b]=k[b][a]=c;
}
int maxx=Dijkstra();
flag=1;
int x=n;
while(x!=1)//回溯1~>n所经过的路径,同时删除
{
//printf("%d<-%d\n",x,pre[x]);
int c=k[x][pre[x]];
k[x][pre[x]]=k[pre[x]][x]=inf;//删除这条边就是假设这条边为inf
maxx=max(maxx,Dijkstra());//保留最坏的情况
k[x][pre[x]]=k[pre[x]][x]=c;//还原
x=pre[x];
}
printf("%d\n",maxx);
}
return 0;
}