Description
Secsa最近对最小生成树问题特别感兴趣。他已经知道如果要去求出一个n个点、m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法。另外,他还知道,某一个图可能有多种不同的最小生成树。例如,下面图 3中所示的都是图 2中的无向图的最小生成树:
当然啦,这些都不是今天需要你解决的问题。Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中。为了使得AB边一定在最小生成树中,你可以对这个无向图进行操作,一次单独的操作是指:先选择一条图中的边 P1P2,再把图中除了这条边以外的边,每一条的权值都减少1。如图 4所示就是一次这样的操作:
Input
输入文件的第一行有3个正整数n、m、Lab分别表示无向图中的点数、边数、必须要在最小生成树中出现的AB边的标号。
接下来m行依次描述标号为1,2,3…m的无向边,每行描述一条边。每个描述包含3个整数x、y、d,表示这条边连接着标号为x、y的点,且这条边的权值为d。
输入文件保证1<=x,y<=N,x不等于y,且输入数据保证这个无向图一定是一个连通图。
Output
输出文件只有一行,这行只有一个整数,即,使得标号为Lab边一定出现最小生成树中的最少操作次数。
Sample Input
4 6 1
1 2 2
1 3 2
1 4 3
2 3 2
2 4 4
3 4 5
1 2 2
1 3 2
1 4 3
2 3 2
2 4 4
3 4 5
Sample Output
1
HINT
第1个样例就是问题描述中的例子。
1<=n<=500,1<=M<=800,1<=D<10^6
Source
Solution
思路很神的一道题。
首先,其他所有边权值-1可以看做这条边+1。如果选定的边本来就在最小生成树上就不用管它。
如果不在MST上的话,就要考虑想办法让它在MST上。让它在MST上的条件是s,t两个联通块之间一定不存在权值比它更小的边。
对于所有比选定的边边权小的边,让它一定不出现在MST上的代价就是让它的边权变为选定的边权+1。问题就变成了选定一些边使得s和t不连通,且边权总和最小。然后就变成了最小割模型,用网络流来解决。
Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 #define maxn 510 6 #define maxm 810 7 #define R register 8 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) 9 #define inf 0x7fffffff 10 int n; 11 struct edge {int a, b, w; } ee[maxm]; 12 struct Edge { 13 Edge *next, *rev; 14 int to, cap; 15 } *cur[maxn], *last[maxn], e[maxm << 2], *ecnt = e; 16 inline void link(R int a, R int b, R int w) 17 { 18 *++ecnt = (Edge) {last[a], ecnt + 1, b, w}; last[a] = ecnt; 19 *++ecnt = (Edge) {last[b], ecnt - 1, a, 0}; last[b] = ecnt; 20 } 21 int s, t, dep[maxn], q[maxn], ans; 22 inline bool bfs() 23 { 24 R int head = 0, tail = 1; 25 memset(dep, -1, (n + 1) << 2); 26 dep[q[1] = t] = 0; 27 while (head < tail) 28 { 29 R int now = q[++head]; 30 for (R Edge *iter = last[now]; iter; iter = iter -> next) 31 if (iter -> rev -> cap && dep[iter -> to] == -1) 32 dep[q[++tail] = iter -> to] = dep[now] + 1; 33 } 34 return dep[s] != -1; 35 } 36 int dfs(R int x, R int f) 37 { 38 if (x == t) return f; 39 R int used = 0; 40 for (R Edge* &iter = cur[x]; iter; iter = iter -> next) 41 if (iter -> cap && dep[iter -> to] + 1 == dep[x]) 42 { 43 R int v = dfs(iter -> to, dmin(f - used, iter -> cap)); 44 iter -> cap -= v; 45 iter -> rev -> cap += v; 46 used += v; 47 if (used == f) return f; 48 } 49 return used; 50 } 51 inline void dinic() 52 { 53 while (bfs()) 54 { 55 memcpy(cur, last, sizeof cur); 56 ans += dfs(s, inf); 57 } 58 } 59 int main() 60 { 61 R int m, lab; scanf("%d%d%d", &n, &m, &lab); 62 for (R int i = 1; i <= m; ++i) scanf("%d%d%d", &ee[i].a, &ee[i].b, &ee[i].w); 63 for (R int i = 1; i <= m; ++i) 64 if (ee[i].w <= ee[lab].w && i != lab) 65 { 66 link(ee[i].a, ee[i].b, ee[lab].w - ee[i].w + 1); 67 link(ee[i].b, ee[i].a, ee[lab].w - ee[i].w + 1); 68 } 69 s = ee[lab].a; t = ee[lab].b; 70 dinic(); 71 printf("%d ", ans); 72 return 0; 73 }