题目描述
每天早上,约翰都要从他的家里步行去农场,他途中可能要经过其他的一些地方。我们把这些地方和路抽象成一张图,这张图里有 N 个点,共有 M 条边(每条边都是双向边),每条边都有一个长度,约翰的家在第 1 个点,农场在第 N 个点,两个点之间没有重复的边,并且这个图是一个连通图,每次约翰从家里到农场总会选一条最短的路径走。
但是约翰的奶牛们老是给约翰捣乱,奶牛们计划在其中某条路上放一些干草堆来阻碍约翰的行走,干草堆放在哪条路上,那条边的长度就相当于增加了一倍。现在,奶牛们想要知道如何选择一条边放干草堆,才能使约翰从家里到农场花费的路程增加最多。
输入
从文件 rblock.in 中读入数据。
从文件 rblock.in 中读入数据。
第一行是两个正整数 N 和 M。
接下来 M 行,每行三个整数 a,b,c 表示点 a 到点 b 的距离是 c。
输出
输出到文件 rblock.out 中。
输出到文件 rblock.out 中。
输出从家里到农场的最短路径最多会增加的距离。
样例数据
输入 #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
数据范围限制
对于 100% 的数据,满足 1<=N<=250,1<=M<=25000,1<=c<=10^6。
提示
【样例1解释】
当奶牛们把干草堆放在 3-4 的边上时,3-4 的边的长度相当于从 3 变到 6,约翰的最短路径就变成了 1-3-5,总共的距离等于 1+7=8,比原来的最短路长度增加了 2。
思路:打一下暴力,原本以为迪杰斯特拉会超时,没想到AC了,先算一次迪杰斯特拉,算出原本的最短路,再一条一条边乘2,算出之后的最短路的最小值,最后输出相减后的结果。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,ans,sum;
int mi[255],nx[25005],
f[255][255],to[25005];
bool c[255];
int main()
{
freopen("rblock.in","r",stdin);
freopen("rblock.out","w",stdout);
memset(f,0x3f3f3f,sizeof(f));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
f[x][y]=f[y][x]=z,nx[i]=x,to[i]=y;
}
memset(mi,0x7f7f,sizeof(mi));
mi[1]=0;
for(int i=1;i<=n;i++)
{
int x=-1;
for(int j=1;j<=n;j++)
{
if(c[j]==0&&(x==-1||mi[j]<mi[x]))
{
x=j;
}
}
if(x==-1)
{
break;
}
c[x]=1;
for(int j=1;j<=n;j++)
{
if(c[j]==0&&mi[j]>f[x][j]+mi[x])
{
mi[j]=f[x][j]+mi[x];
}
}
}
sum=mi[n];
for(int i=1;i<=m;i++)
{
memset(mi,0x7f7f,sizeof(mi));
memset(c,0,sizeof(c));
mi[1]=0,f[nx[i]][to[i]]*=2,f[to[i]][nx[i]]*=2;
for(int i=1;i<=n;i++)
{
int x=-1;
for(int j=1;j<=n;j++)
{
if(c[j]==0&&(x==-1||mi[j]<mi[x]))
{
x=j;
}
}
if(x==-1)
{
break;
}
c[x]=1;
for(int j=1;j<=n;j++)
{
if(c[j]==0&&mi[j]>f[x][j]+mi[x])
{
mi[j]=f[x][j]+mi[x];
}
}
}
ans=max(ans,mi[n]),f[nx[i]][to[i]]/=2,f[to[i]][nx[i]]/=2;
}
printf("%d",ans-sum);
return 0;
}
328

被折叠的 条评论
为什么被折叠?



