CF716D Complete The Graph
图论+构造
首先可以发现如果去除了可以改变权值的边,$s$到$t$的最短路若小于$l$,那么一定不行
若等于则直接将可改边权的边改为inf,输出即可
那么现在原图中的最短路是大于$l$的
因为每一条边是都要加入图中的,而且每条边边权至少为1
那么可以不断向图中加入权值为1的边,并且在加边的过程中不断跑最短路
如果加完当前的边,$s$到$t$的最短路小于l的话,将这条边权值增加
剩下的边边权改为inf即可
简单证明这种做法
首先考虑加入1边后,最短路依然大于$l$,那么继续使最短路减小
再考虑加入1边后,最短路小于$l$
因为在加入这条边之前最短路大于$l$,那么加入这条边后,最短路肯定经过这条边
而增加边权之后,最短路还是比之前的小,那么最短依然经过这条边
不会出现增加了这条边的边权之后,最短路不经过这条边的情况
那么得到的图最短路必定为$l$
#include <bits/stdc++.h> #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 <int> q; for (int i=0;i<n;i++) d[i]=inf; d[s]=0; vi[s]=1; q.push(s); while (!q.empty()) { int f; f=q.front(); q.pop(); vi[f]=0; for (int i=first[f];i!=-1;i=nxt[i]) { int u; u=point[i]; if (d[u]>d[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) { printf("NO\n"); return 0; } if (d[t]==l)//注意 { printf("YES\n"); for (int i=1;i<=m;i++) { if (sh[i].l==0) sh[i].l=inf; printf("%d %d %lld\n",sh[i].u,sh[i].v,sh[i].l); } return 0; } int wh; for (int i=1;i<=m;i++) { if (sh[i].l==0) { add_edge(sh[i].u,sh[i].v,1); add_edge(sh[i].v,sh[i].u,1); 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); }