题目描述
每天早晨,FJ从家中穿过农场走到牛棚。农场由 N 块农田组成,农田通过 M 条双向道路连接,每条路有一定长度。FJ 的房子在 1 号田,牛棚在 N 号田。没有两块田被多条道路连接,以适当的路径顺序总是能在农场任意一对田间行走。当FJ从一块田走到另一块时,总是以总路长最短的道路顺序来走。
FJ 的牛呢,总是不安好心,决定干扰他每天早晨的计划。它们在 M 条路的某一条上安放一叠稻草堆,使这条路的长度加倍。牛希望选择一条路干扰使得FJ 从家到牛棚的路长增加最多。它们请你设计并告诉它们最大增量是多少。
输入格式
第 1 行:两个整数 N, M。
第 2 到 M+1 行:第 i+1 行包含三个整数 A_i, B_i, L_i,A_i 和 B_i 表示道路 i 连接的田的编号,L_i 表示路长。
输出格式
第 1 行:一个整数,表示通过使某条路加倍而得到的最大增量。
输入输出样例
输入 #1
5 7 2 1 5 1 3 1 3 2 8 3 5 7 3 4 3 2 4 7 4 5 2
输出 #1
2
说明/提示
【样例说明】
若使 3 和 4 之间的道路长加倍,最短路将由 1-3-4-5 变为 1-3-5。
【数据规模和约定】
对于 30%的数据,N <= 70,M <= 1,500。
对于 100%的数据,1 <= N <= 100,1 <= M <= 5,000,1 <= L_i <= 1,000,000。
【解题思路】
最短路
【code】
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define M 15000 5 #include<queue> 6 #define N 110 7 using namespace std; 8 int n,m; 9 int po,ans; 10 int head[N],to[M],next[M],len[M],e=1; 11 void buid(int u,int v,int l) 12 { 13 next[++e]=head[u],head[u]=e; 14 to[e]=v,len[e]=l; 15 } 16 int dis[N],init[N]; 17 int pre[N],fr[N],that[M],nu; 18 queue<int> q; 19 void spfa(int s) 20 { 21 memset(dis,20,sizeof(dis)); 22 dis[s]=0;init[s]=1,q.push(s); 23 while(!q.empty()) 24 { 25 int now=q.front();q.pop();init[now]=0; 26 for(int i=head[now];i;i=next[i]) 27 { 28 int j=to[i]; 29 if(dis[j]>dis[now]+len[i]) 30 { 31 dis[j]=dis[now]+len[i]; 32 pre[j]=i;fr[j]=now; 33 if(!init[j]) 34 { 35 init[j]=1;q.push(j); 36 } 37 } 38 } 39 } 40 } 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for(int i=1;i<=m;++i) 45 { 46 int u,v,l; 47 scanf("%d%d%d",&u,&v,&l); 48 buid(u,v,l); 49 buid(v,u,l); 50 } 51 spfa(1);po=dis[n]; 52 int now=n; 53 while(now!=1) 54 { 55 that[++nu]=pre[now];//记路径 56 now=fr[now]; 57 } 58 for(int i=1;i<=nu;++i)//枚举路径 59 { 60 len[that[i]]*=2; 61 len[that[i]^1]*=2; 62 spfa(1);//操♂作 63 ans=max(ans,dis[n]); 64 len[that[i]]/=2; 65 len[that[i]^1]/=2; 66 } 67 cout<<ans-po<<endl;//end 68 return 0; 69 }