[最小割][Kruskal] Luogu P5039 最小生成树

题目描述

Secsa最近对最小生成树问题特别感兴趣。他已经知道如果要去求出一个 nn 个点、 mm 条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法。另外,他还知道,某一个图可能有多种不同的最小生成树。例如,下面图3中所示的都是图2中的无向图的最小生成树:

当然啦,这些都不是今天需要你解决的问题。Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中。为了使得AB边一定在最小生成树中,你可以对这个无向图进行操作,一次单独的操作是指:先选择一条图中的边 P1P2,再把图中除了这条边以外的边,每一条的权值都减少 11 。如图4所示就是一次这样的操作:

题解

  • 我们可以发现让其余所有边都减1和让自己加1没什么区别

  • 考虑kruskal的过程,首先边权大于这条边的是不用考虑的

  • 考虑把那些边权比这条边小的调节到比这条边大,这样就相当于在生成树上去掉了这条边

  • 至于调大到多少自然是使得边权恰好大1

  • 让这条边必然存在就一定得让这条边链接的两个点不连通,于是我们把在生成树上去掉这条边看成割断这条边,于是这就是一个最小割

代码

 1 #include <queue>
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N=1010;
 7 queue<int> Q;
 8 struct edge{int to,from,w;}e[N*4];
 9 struct node{int u,v,w,o;}E[N];
10 int n,m,S,T,k,t,cnt=1,ans,head[N],d[N],cur[N];
11 int cmp(node a,node b) { return a.w==b.w?a.o<b.o:a.w<b.w; }
12 void insert(int x,int y,int w) 
13 {
14     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt,e[cnt].w=w;
15     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt,e[cnt].w=0;
16 }
17 int bfs() 
18 {
19     for(int i=1;i<=n;i++) d[i]=0,cur[i]=head[i];
20     Q.push(S),d[S]=1;
21     while (!Q.empty()) 
22     {
23         int u=Q.front(); Q.pop();
24         for (int i=head[u];i;i=e[i].from) if (!d[e[i].to]&&e[i].w) d[e[i].to]=d[u]+1,Q.push(e[i].to);
25     }
26     return d[T];
27 }
28 int dfs(int x,int now) 
29 {
30     if (x==T||!now) return now;
31     int flow=0,ff;
32     for (int& i=cur[x];i;i=e[i].from)
33         if (d[e[i].to]==d[x]+1) 
34         {
35             ff=dfs(e[i].to,min(now,e[i].w));
36             if (ff<=0) continue;
37             now-=ff,flow+=ff,e[i].w-=ff,e[i^1].w+=ff;
38             if (!now) break;
39         }
40     return flow;
41 }
42 int main() 
43 {
44     scanf("%d%d%d",&n,&m,&k);
45     for (int i=1;i<=m;i++) scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);
46     E[k].o=1,S=E[k].u,T=E[k].v,t=E[k].w,sort(E+1,E+m+1,cmp);
47     for (int i=1;i<=m;i++) { if (E[i].o) break; insert(E[i].u,E[i].v,t-E[i].w+1),insert(E[i].v,E[i].u,t-E[i].w+1); }
48     while (bfs()) ans+=dfs(S,999999999); printf("%d",ans);
49 }
原文地址:https://www.cnblogs.com/Comfortable/p/11280486.html