有一个无向图,共N个节点,编号1至N,共M条边。FJ在节点1,它想到达节点N。FJ总是会选择最短路径到达节点N
。作为捣蛋的奶牛Bessie,它想尽量延迟FJ到达节点N的时间,于是Bessie决定从M条边之中选择某一条边,使得改
边的长度变成原来的两倍,由于智商的问题,Bessie不知道选择加倍哪条边的长度才能使得FJ到达N号节点的时间
最迟。注意:不管Bessie选择加倍哪条边的长度,FJ总是会从1号节点开始走最短路径到达N号点。
Input
第一行,两个整数N和M. 1 <=N<=250, 1<=M<=250000。
接下来有M行,每行三个整数:A,B,L,表示节点A和节点B之间有一条长度为L的无向边。1<=L<=1000000。
Output
一个整数。Bessie选择了加倍某一条边的长度后,奶牛FJ从节点1到达节点N的最短路径是多少。但是输出的格式
有变化,假设Bessie没有加倍某一条边的长度之前,FJ从1号节点到达N号节点的最短路径是X;在Bessie加倍某一
条边的长度之后,FJ从1号节点到达N号节点的最短路径是Y,那么你输出的结果是Y-X。
Sample Input
5 7
2 1 5
1 3 1
3 2 8
3 5 7
3 4 3
2 4 7
4 5 2
INPUT DETAILS: There are 5 fields and 7 pathways. Currently, the shortest path from the house (field 1) to the barn (field 5) is 1-3-4-5 of total length 1+3+2=6.
Sample Output
2
(把节点3到节点4的边从原来的长度3变成长度6)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<map> #include<queue> #include<set> #define ll long long #define llu unsigned ll using namespace std; const int mod=1000000007; const int maxn=50100; const int maxx=300; const int inf=0x3f3f3f3f; int head[maxx],edge[maxn],ver[maxn],nt[maxn]; int d[maxx]; int ha[maxx]; int pre[maxx]; int tot=1,n,m; bool flag=false; void add(int x,int y,int z) { ver[++tot]=y,edge[tot]=z; nt[tot]=head[x],head[x]=tot; } int Dij(void) { memset(d,0x3f,sizeof(d)); memset(ha,0,sizeof(ha)); d[1]=0; priority_queue<pair<int,int> >q;//默认为大根堆 q.push(make_pair(0,1)); while(q.size()) { int x=q.top().second; q.pop(); if(ha[x]) continue; ha[x]=true; for(int i=head[x];i;i=nt[i]) { int y=ver[i],z=edge[i]; if(d[y]>d[x]+z) { d[y]=d[x]+z; if(!flag) //最开始算最短路时,记上y点在最短路上的父亲边是哪条边 pre[y]=i; q.push(make_pair(-d[y],y)); } } } return d[n]; } int main(void) { scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } int cnt=Dij(); flag=true; int _max=0; for(int i=2;i<=n;i++)//枚举点 { int k=pre[i]; if (k==0)//如果不在最短路径上就不管了 continue; edge[k]=edge[k]*2,edge[k^1]=edge[k^1]*2; _max=max(_max,Dij()); edge[k]=edge[k]/2,edge[k^1]=edge[k^1]/2; } printf("%d\n",_max-cnt); return 0; }