【图论 思维】cf715B. Complete The Graph加强

zzq讲的杂题

题目大意

有一张$n​$个点$m​$条边的简单正权无向图,$S​$到$T​$的最短路为$L​$,现在有一些边的边权未知,请输出任意一种满足题意的方案。

$n,mle 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(nlog 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
",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

原文地址:https://www.cnblogs.com/antiquality/p/10776547.html