CF-715B Complete The Graph
题意
给 n,(2≤n≤1000) 点 m,(1≤m≤10000) 边的无向图,修改 m 条边中边为 0 的边,使满足 s,t,(0≤s,t,ui,vi≤n−1,s=t,0≤wi≤109) 的最短路长度是 L,(0≤L≤109) ,且输出答案的时候边为 0 的边的权值必须在 [1,1018] 内。
题解
把所有为零的边赋为 1 跑一遍最短路,用 dis 表示,显然若 dist>L 输出无解。
然后我们有一个naive的想法,给那些可修改的边依次 +1,(可以修改的边权为 w1,w2,…,we,我们的“操作序列”便是 w1=2,w2=2,…,we=2,w1=3,w2=3,…,we=3,…we=L),操作序列的长度为 e(L−1) ,e 为可修改的边数。显然如果执行完“操作序列”,dist′<L 肯定无解,不然在某次修改后 dist′=L ,因为一次修改最多让 dist′ 增加 1
二分操作序列,每次跑一遍 Dijkstra ,复杂度 O(nlognlog(ml)) ,能过,但有更优秀的做法。
考虑在第一次 Dijkstra (可修改的边权赋 1)后处理出 disi ,记 dif=L−dist ,dif<0 无解。 再跑一遍 Dijkstra ,dis′ 为新的距离,此时对于任意一条边 (u,v) 若 disu′+wu→v<disv+dif 修改边权 wu→v′=disv+dif−disu′ ,若最后 dist=L 则无解。
考虑这样做为毛是对的,根据上面naive的想法,若所有边都赋最大值最短路还比 L 小就无解,不然一定有解。
我们的修改保证了 disu′+wu→v′≥disv+dif ,故可以保证 dist′≥L 。再考虑一定存在一条最短的路径满足 disu′+wu→v′=disv+dif=disv′ ,故 dist′=L 。
CODE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
   | #include <bits/stdc++.h> #define inf (L+100) using namespace std; template<typename T> inline void red(T &x) {     x=0;bool fg=0;char ch=getchar();     while(ch<'0'||ch>'9') {if(ch=='-') fg^=1;ch=getchar();}     while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(T)(ch^48),ch=getchar();     if(fg) x=-x; } const int N = 1005; const int M = 10005; typedef long long ll; typedef pair<int,int> pii; int head[N],nxt[M<<1],pnt[M<<1],wth[M<<1],E=-1; int n,m,s,t,L,dif; bool can[M<<1]; ll ds[2][N]; vector<int> e; bool vis[N]; void adde(int u,int v,int w) {     E++;pnt[E]=v;nxt[E]=head[u];wth[E]=w;head[u]=E;     if(w==0) e.push_back(E),can[E]=1; } void dij(bool fg) {     memset(ds[fg],0x3f,sizeof(ds[fg]));     ds[fg][s]=0;     memset(vis,0,sizeof(vis));     priority_queue<pii> q;q.push(pii(0,s));     while(!q.empty()) {         int u=q.top().second;q.pop();         if(vis[u]) continue;         vis[u]=1;         for(int i=head[u];i!=-1;i=nxt[i]) {             int v=pnt[i];             if(fg&&can[i]) {                 if(ds[1][u]+wth[i]<ds[0][v]+dif) wth[i]=wth[i^1]=ds[0][v]+dif-ds[1][u];                           }             if(ds[fg][u]+wth[i]<ds[fg][v]) {                 ds[fg][v]=ds[fg][u]+wth[i];                 q.push(pii(-ds[fg][v],v));             }         }     } } int main() {     red(n);red(m);red(L);red(s);red(t);     memset(head,-1,sizeof(head));     for(int i=1;i<=m;i++) {         int u,v,w;         red(u);red(v);red(w);         adde(u,v,w);adde(v,u,w);     }     for(auto i:e) wth[i]=1;     dij(0);     if(ds[0][t]>L) {puts("NO");return 0;}      dif=L-ds[0][t];     dij(1);     if(ds[1][t]!=L) {puts("NO");return 0;}      puts("YES");     for(int i=0;i<=E;i+=2) {         printf("%d %d %d\n",pnt[i^1],pnt[i],wth[i]);     }     return 0; }
   |