最小割定义
- 割 : 点的划分方式, 将图中的所有点划分成2个集合,源点s,汇点t, s ∈ S , t ∈ T s\in S,t \in T s∈S,t∈T.
- 割的容量 : 表示所有从
S
到T
的边的容量之和, c ( S , T ) = Σ u ∈ S , v ∈ T c ( u , v ) c(S,T) = \Sigma_{u \in S,v \in T}c(u,v) c(S,T)=Σu∈S,v∈Tc(u,v) - 最小割问题: 求一个割的方法使得割的容量最小
最大流 = 最小割
- 求最小割和最大流可以看做是一个问题
最小割例题 luogu P1344
问题
- 最小割的值
- 最小割边的个数
直接求最小割
- 第一问直接求最大流
- 对于第二问重新建图 将边权改为1,那么最大流=最小割=最小割的边数
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 50;
const int maxm = 1e4+5;
const ll inf = 1e9+1;
struct Edge{
int v,next;
ll c;
} edge[maxm];
int n,m,tot,source,sink;
int head[maxn],dep[maxn];
void add(int u,int v,ll c) {
edge[tot].v=v; edge[tot].c=c;
edge[tot].next=head[u]; head[u]=tot++;
}
void addedge(int u,int v,ll c) {
add(u,v,c);
add(v,u,0);
}
bool bfs() {
queue<int> que;
memset(dep,-1,sizeof dep);
dep[source] = 0; // 深度标记数组
que.push(source);
while (!que.empty()) {
int cur = que.front(); que.pop();
for (int i=head[cur]; i!=-1; i=edge[i].next) {
int to = edge[i].v;
if (edge[i].c>0 && dep[to]==-1) {
dep[to] = dep[cur] + 1;
que.push(to);
}
}
}
return dep[sink] != -1;
}
ll dfs(int u,ll delta) {
if (u == sink)
return delta;
ll flow = 0;
for (int i=head[u]; i!=-1; i=edge[i].next) {
int to = edge[i].v;
if (edge[i].c>0 && dep[to]==dep[u]+1) {
ll temp = dfs(to,min(delta-flow,edge[i].c));
edge[i].c -= temp;
edge[i^1].c += temp;
flow += temp;
}
}
if (!flow) dep[u] = -1;
return flow;
}
ll Dinic() {
ll ans = 0;
while(bfs()) {
while (1) {
ll temp = dfs(source,inf);
if (!temp) break;
ans += temp;
}
}
return ans;
}
struct Storage {
int u,v;
} storage[maxm];
int main() {
memset(head,-1,sizeof head);
scanf("%d%d",&n,&m);
source = 1;
sink = n;
for (int i=1; i<=m; ++i) {
int u,v;
ll c;
scanf("%d %d %lld",&u,&v,&c);
addedge(u,v,c);
storage[i].u = u;
storage[i].v = v;
}
ll maxflow = Dinic();
// 重新建图求 最小割的数量
memset(head,-1,sizeof head);
memset(edge,0,sizeof edge);
tot = 0;
for (int i=1; i<=m; ++i)
addedge(storage[i].u,storage[i].v,1);
ll cut_count = Dinic();
cout << maxflow << " " << cut_count << endl;
return 0;
}
最小割转最大流
- 建图时边权 w = k ∗ w + 1 w=k*w+1 w=k∗w+1, 若 S S S为最小割边集 则 w i ∈ S w_i \in S wi∈S
w 1 + w 2 + w 3 + . . . + w n = a n s w_1+w_2+w_3+...+w_n = ans w1+w2+w3+...+wn=ans
w 1 ∗ k + w 2 ∗ k + w 3 ∗ k + . . . + w n ∗ k = a n s ∗ k w_1*k+w_2*k+w_3*k+...+w_n*k = ans*k w1∗k+w2∗k+w3∗k+...+wn∗k=ans∗k
( w 1 ∗ k + 1 ) + ( w 2 ∗ k + 1 ) + ( w 3 ∗ k + 1 ) + . . . + ( w n ∗ k + 1 ) = a n s ∗ k + n = a n s 1 (w_1*k+1)+(w_2*k+1)+(w_3*k+1)+...+(w_n*k+1) = ans*k+n = ans_1 (w1∗k+1)+(w2∗k+1)+(w3∗k+1)+...+(wn∗k+1)=ans∗k+n=ans1
- 最小割: a n s = a n s 1 / k ans = ans_1/k ans=ans1/k
- 最大流: c u t = a n s 1 % k cut=ans_1 \% k cut=ans1%k
- 注意
long long
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 50;
const int maxm = 1e4+5;
const ll mod = 2000;
const ll inf = 1e9+1;
struct Edge {
int v,next;
ll c;
}edge[maxm];
int head[maxn],dep[maxn];
int n,m,tot,source,sink;
void add(int u,int v,ll c){
edge[tot].v=v; edge[tot].c=c;
edge[tot].next=head[u]; head[u]=tot++;
}
void addedge(int u,int v,ll c) {
add(u,v,c);
add(v,u,0);
}
bool bfs() {
queue<int> que;
memset(dep,-1,sizeof dep);
dep[source] = 0;
que.push(source);
while(!que.empty()) {
int cur = que.front(); que.pop();
for (int i=head[cur]; i!=-1; i=edge[i].next) {
int to = edge[i].v;
if (edge[i].c>0 && dep[to] == -1) {
dep[to] = dep[cur] + 1;
que.push(to);
}
}
}
return dep[sink] != -1;
}
ll dfs(int u,int delta) {
if (u == sink)
return delta;
ll flow = 0;
for (int i=head[u]; i!=-1; i=edge[i].next) {
int to = edge[i].v;
if (edge[i].c>0 && dep[to]==dep[u]+1) {
ll temp = dfs(to,min(delta-flow,edge[i].c));
edge[i].c -= temp;
edge[i^1].c += temp;
flow += temp;
}
}
if (!flow) dep[u] = -1;
return flow;
}
ll Dinic() {
ll ans=0;
while (bfs()) {
while(1) {
ll temp = dfs(source,inf);
if (!temp) break;
ans += temp;
}
}
return ans;
}
int main() {
memset(head,-1,sizeof head);
scanf("%d%d",&n,&m);
for (int i=1; i<=m; ++i) {
int u,v;
ll c;
scanf("%d%d%lld",&u,&v,&c);
addedge(u,v,c*mod+1);
}
source = 1;
sink = n;
ll ans = Dinic();
cout << ans/mod << " " << ans%mod << endl;
return 0;
}
- 2019/11/18 0:36:23 真晚