CF716D Complete The Graph
阅读原文时间:2023年07月08日阅读:1

图论+构造

首先可以发现如果去除了可以改变权值的边,$s$到$t$的最短路若小于$l$,那么一定不行

若等于则直接将可改边权的边改为inf,输出即可

那么现在原图中的最短路是大于$l$的

因为每一条边是都要加入图中的,而且每条边边权至少为1

那么可以不断向图中加入权值为1的边,并且在加边的过程中不断跑最短路

如果加完当前的边,$s$到$t$的最短路小于l的话,将这条边权值增加

剩下的边边权改为inf即可

简单证明这种做法

首先考虑加入1边后,最短路依然大于$l$,那么继续使最短路减小

再考虑加入1边后,最短路小于$l$

因为在加入这条边之前最短路大于$l$,那么加入这条边后,最短路肯定经过这条边

而增加边权之后,最短路还是比之前的小,那么最短依然经过这条边

不会出现增加了这条边的边权之后,最短路不经过这条边的情况

那么得到的图最短路必定为$l$

#include
#define ll long long
#define inf (ll)1e17;
using namespace std;
const int MAXN=20100;
int n,m,l,s,t,tot;
int first[1100],nxt[MAXN],point[MAXN];
int vi[1100];
ll d[1100],len[MAXN];
struct node
{
int u,v;
ll l;
}sh[MAXN];
void add_edge(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
point[tot]=y;
len[tot]=z;
}
void spfa()//最短路
{
queue q;
for (int i=0;id[f]+len[i])
{
d[u]=d[f]+len[i];
if (!vi[u])
{
vi[u]=1;
q.push(u);
}
}
}
}
}
int main()
{
tot=-1;
memset(first,-1,sizeof(first));
memset(nxt,-1,sizeof(nxt));
scanf("%d%d%d%d%d",&n,&m,&l,&s,&t);
for (int i=1;i<=m;i++) { scanf("%d%d%lld",&sh[i].u,&sh[i].v,&sh[i].l); if (sh[i].l==0) continue; add_edge(sh[i].u,sh[i].v,sh[i].l); add_edge(sh[i].v,sh[i].u,sh[i].l); } spfa(); if (d[t]l)
{
sh[i].l=1;
continue;
}
sh[i].l=1+l-d[t];
wh=i;
break;
}
}
tot=-1;
memset(first,-1,sizeof(first));
memset(nxt,-1,sizeof(nxt));
for (int i=wh+1;i<=m;i++)
{
if (sh[i].l==0)
sh[i].l=inf;
}
for (int i=1;i<=m;i++)
{
add_edge(sh[i].u,sh[i].v,sh[i].l);
add_edge(sh[i].v,sh[i].u,sh[i].l);
}
spfa();
if (d[t]!=l)
{
printf("NO\n");
return 0;
}
printf("YES\n");
for (int i=1;i<=m;i++)
printf("%d %d %lld\n",sh[i].u,sh[i].v,sh[i].l);
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器