【图论 思维】cf715B. Complete The Graph加强
zzq讲的杂题
题目大意
有一张$n$个点$m$条边的简单正权无向图,$S$到$T$的最短路为$L$,现在有一些边的边权未知,请输出任意一种满足题意的方案。
$n,m\le 500000$.
题目分析
首先对于每一条边权未定的边,把它的边权设为1,处理出$dist_i$表示在这种情况下,$T$到$i$的最短路距离。之后再从$S$开始做dij,设$S$到$u$的最短路为$len_i$,那么当前若以$u$为起点增广一条边权未定的边$(u,v)$,就将其边权设为$\max\{1,L-len_u-dist_v\}$。最后若$T$的最短路不为$L$则无解。
关于第二次重设边权,如上处理之后在有解情况下显然第二次dij出的$len_i \le L$,那么剩下的就是考虑:可不可能把一条$L$的最短路给刷得更小了。
分步地看这个问题,我们最后一次进行重设边权操作时,等于说是钦定了一条过这个边的长度为$L$的路径(因为$len_i$是依靠重新设的边权做的最短路),也就是说一定是满足条件的最短路。反之如果这个做法无解,说明任意的未定边权的边都不在长为$L$的最短路上,那么也就没有任何影响。
注意如果(像我一样偷懒不刷完全图)那么需要判一判未经过的边。
时间复杂度:$O(n\log n)$
1 #include<bits/stdc++.h> 2 typedef long long ll; 3 const int maxn = 1035; 4 const int maxm = 20035; 5 const ll INF = 1000000000000000000ll; 6 7 struct Edge 8 { 9 int v; 10 ll val; 11 Edge(int a=0, int b=0):v(a),val(b) {} 12 }edges[maxm]; 13 struct node 14 { 15 int x; 16 ll d; 17 node(int a=0, ll b=0):x(a),d(b) {} 18 bool operator < (node a) const 19 { 20 return d > a.d; 21 } 22 }; 23 int n,m,L,S,T; 24 int edgeTot,head[maxn],nxt[maxm]; 25 ll dis[maxn],len[maxn]; 26 int dfn[maxn],tim; 27 std::priority_queue<node> q; 28 29 int read() 30 { 31 char ch = getchar(); 32 int num = 0, fl = 1; 33 for (; !isdigit(ch); ch=getchar()) 34 if (ch=='-') fl = -1; 35 for (; isdigit(ch); ch=getchar()) 36 num = (num<<1)+(num<<3)+ch-48; 37 return num*fl; 38 } 39 void addedge() 40 { 41 int u = read()+1, v = read()+1, c = read(); 42 edges[edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot; 43 edges[edgeTot] = Edge(u, c), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot; 44 } 45 int main() 46 { 47 memset(head, -1, sizeof head); 48 n = read(), m = read(), L = read(), S = read()+1, T = read()+1; 49 for (int i=1; i<=m; i++) addedge(); 50 memset(dis, 0x3f3f3f3f, sizeof dis); 51 tim = 1, q.push(node(T, 0)), dis[T] = 0; 52 for (int tmp; q.size(); ) 53 { 54 tmp = q.top().x, q.pop(); 55 if (dfn[tmp]==tim) continue; 56 dfn[tmp] = tim; 57 for (int i=head[tmp]; i!=-1; i=nxt[i]) 58 { 59 int v = edges[i].v, c = edges[i].val?edges[i].val:1; 60 if (dis[v] > dis[tmp]+c) dis[v] = dis[tmp]+c, q.push(node(v, dis[v])); 61 } 62 } 63 memset(len, 0x3f3f3f3f, sizeof len); 64 tim = 2, q.push(node(S, 0)), len[S] = 0; 65 for (int tmp; q.size(); ) 66 { 67 tmp = q.top().x, q.pop(); 68 if (dfn[tmp]==tim) continue; 69 dfn[tmp] = tim; 70 if (tmp==T){ 71 if (len[T]!=L) puts("NO"); 72 else{ 73 puts("YES"); 74 for (int i=1; i<=n; i++) 75 for (int j=head[i]; j!=-1; j=nxt[j]) 76 if (edges[j].v > i) printf("%d %d %lld\n",i-1,edges[j].v-1,edges[j].val?edges[j].val:INF); 77 } 78 return 0; 79 } 80 for (int i=head[tmp]; i!=-1; i=nxt[i]) 81 { 82 if (!edges[i].val){ 83 edges[i].val = edges[i^1].val = std::max(L-len[tmp]-dis[edges[i].v], 1ll); 84 } 85 int v = edges[i].v, c = edges[i].val; 86 if (len[v] > len[tmp]+c) len[v] = len[tmp]+c, q.push(node(v, len[v])); 87 } 88 } 89 puts("NO"); 90 return 0; 91 }
END