【LuoguP2176】RoadBlocks
作者:互联网
https://www.luogu.com.cn/problem/P2177
分析
1、首先,先走一遍最短路,记录这条路经过的点。现在路径分为两种:1、最短路;2、非最短路
2、加倍操作的路径如果不属于最短路,则对它没有影响,因此增量为0,所以加倍操作的路径一定属于最短路
3、现在遍历最短路,操作每一条路径并且复原
a、遍历一次:加倍操作->现在路径分为两种:1、包括被操作的;2、不包括被操作的。
b、在1中最短路一定是原来的最短路长度n+被操作加倍的长度n'
c、在2中最短路是把被操作的路删掉以后的最短路
最后debug:dijkstra()函数必须传入一个vector
#include <bits/stdc++.h>
using namespace std;
#define P pair<long long,int>
#define dP pair<int, long long> //前置节点 最短距离
#define INF 0x3fffffffffffffff
int n,m,s,e;
long long l,a[105][105]={0};
dP d[105];
vector<int> path0,path1;
void dijkstra(vector<int> &path)
{
for(int i=0;i<105;i++)d[i].second=INF;
d[1].first=0;d[1].second=0;
path.clear();
priority_queue<P,vector<P>,greater<P>> Q;
Q.push(P(0,1)); //当前距离 当前标号
while(!Q.empty())
{
P tmp=Q.top();Q.pop();
int index=tmp.second,id=tmp.first;
if(id>d[index].second)continue;
for(int i=1;i<=n;i++)
{
long long nd=id+a[index][i];
if(nd<d[i].second)
{
d[i].second=nd;
d[i].first=index;
Q.push(P(nd,i));
}
}
}
int pre=n;
while(pre!=0)
{
path.push_back(pre);
pre=d[pre].first;
}
reverse(path.begin(),path.end());
/*for(auto x:path)cout<<x<<" ";
cout<<endl;*/
}
int main()
{
freopen("P2176_7.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=0;i<105;i++)
{
for(int j=0;j<105;j++)if(i!=j)a[i][j]=INF;
}
while(m--)
{
scanf("%d%d%lld",&s,&e,&l);
a[s][e]=l;a[e][s]=l;
}
dijkstra(path0);
long long ori_dist=d[n].second,now_min_dist=0,ans=-1;
int l=path0.size();
for(int i=0;i<l-1;i++)
{
int sn=path0[i],en=path0[i+1],k=a[sn][en];
a[sn][en]=INF;a[en][sn]=INF;
dijkstra(path1);
long long now_dist=d[n].second;
a[sn][en]=k;a[en][sn]=k;
//cout<<k<<" "<<ori_dist<<" "<<now_dist<<endl;
now_min_dist=min(now_dist,ori_dist+k);
if(ans<now_min_dist-ori_dist)ans=now_min_dist-ori_dist;
}
printf("%lld\n",ans);
return 0;
}
标签:int,短路,路径,LuoguP2176,加倍,RoadBlocks,操作,path 来源: https://www.cnblogs.com/tsyxxxka/p/15358393.html