题目来源
洛谷P2176 [USACO14FEB]路障Roadblock
https://daniu.luogu.org/problem/show?pid=2176
思路
建图 求最短路长度len并记录路径 初始化答案为ans
枚举最短路路径中的边 把这条边的长度加倍 求此时的最短路长度
如果该长度与len的差大于ans 更新ans为该长度-len 还原该边长 继续枚举
代码(C++)
#include <cstdio>
#include <queue>
#include <bitset>
using namespace std;
bitset<110> in; queue<int> q;
long long dis[1010]={0},length,ans=0;
int n,m,u,v,w,cnt=0,pos,he[110],f[110];
int en[10010],ne[10010],len[10010],fr[10010];
inline void add();
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
scanf("%d%d%d",&u,&v,&w),add();
for(int j=1;j<n;++j)
dis[j]=9223372036854775807;
in[n]=1; q.push(n);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
for(int k=he[pos];k!=0;k=ne[k])
if(dis[pos]+len[k]<dis[en[k]])
{
dis[en[k]]=dis[pos]+len[k];
f[en[k]]=k;
if(in[en[k]]==0)
q.push(en[k]),in[en[k]]=1;
}
}
length=dis[1];
for(int i=f[1];i!=0;i=f[fr[i]])
{
for(int j=1;j<n;++j)
dis[j]=9223372036854775807;
len[i]*=2; in=0; in[n]=1; q.push(n);
while(!q.empty())
{
pos=q.front(); q.pop(); in[pos]=0;
for(int k=he[pos];k!=0;k=ne[k])
if(dis[pos]+len[k]<dis[en[k]])
{
dis[en[k]]=dis[pos]+len[k];
if(in[en[k]]==0)
q.push(en[k]),in[en[k]]=1;
}
}
len[i]/=2; in=0;
if(dis[1]-length>ans)
ans=dis[1]-length;
}
printf("%lld",ans);
return 0;
}
inline void add()
{
en[++cnt]=v; len[cnt]=w;
ne[cnt]=he[u]; he[u]=cnt; fr[cnt]=u;
en[++cnt]=u; len[cnt]=w;
ne[cnt]=he[v]; he[v]=cnt; fr[cnt]=v;
}