# ACM/ICPC 之 Dinic+枚举最小割点集(可做模板)(POJ1815)

最小割的好题，可用作模板。

```//Dinic+枚举字典序最小的最小割点集
//Time:1032Ms   Memory:1492K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

#define MAXN 205
#define INF 0x3f3f3f3f

int N, S, T;
int s,t;
int sres[2*MAXN][2*MAXN];   //source-res
int res[2*MAXN][2*MAXN];
int d[2*MAXN];
int cut[MAXN];  //最小割点集
bool v[2*MAXN];

bool bfs()
{
memset(d, -1, sizeof(d));
queue<int> q;
q.push(s);  d[s] = 0;
while(!q.empty() && d[t] == -1){
int cur = q.front();    q.pop();
for(int i = 1; i <= t; i++)
{
if(d[i] == -1 && res[cur][i])
{
d[i] = d[cur] + 1;
q.push(i);
}
}
}
return d[t] != -1;
}

int dfs(int x, int sum)
{
if(x == t || sum == 0)  return sum;
int src = sum;
for(int i = 1; i <= t; i++)
{
if(d[i] == d[x] + 1 && res[x][i])
{
int tmp = dfs(i, min(sum, res[x][i]));
res[x][i] -= tmp;
res[i][x] += tmp;
sum -= tmp;
}
}
return src - sum;
}

int Dinic()
{
memcpy(res, sres, sizeof(sres));
int maxFlow = 0;
while(bfs())
maxFlow += dfs(s,INF);
return maxFlow;
}

int main()
{
//freopen("in.txt", "r", stdin);

while(~scanf("%d%d%d", &N,&S,&T))
{
memset(sres, 0 ,sizeof(sres));
s = 0;  t = 2*N+1;
sres[0][S] = sres[T+N][t] = INF;
for(int i = 1; i <= N; i++)
{
sres[i][i + N] = 1;
for(int j = 1; j <= N; j++)
{
int num;
scanf("%d", &num);
if(num && i != j) sres[i+N][j] = INF;
}
}
sres[S][S+N] = sres[T][T+N] = INF;
int ans = Dinic();
if(ans == INF){ //不可分开
continue;
}
else {
printf("%d\n", ans);
if(ans == 0) continue;  //已经分开
}

//枚举最小割点集
int len = 0, tmp = ans;
for(int i = 1; i <= N && tmp; i++)
{
if(i == S || i == T)   continue;
if(res[i][i+N])    continue;
sres[i][i+N] = 0;
int k = Dinic();
if(k != tmp){
tmp = k;
cut[len++] = i;
}
else sres[i][i+N] = 1;
}
for(int i = 0; i < ans - 1; i++)
printf("%d ", cut[i]);
printf("%d\n", cut[ans-1]);
}

return 0;
}
```

原文作者：Inkblots
原文地址: https://www.cnblogs.com/Inkblots/p/5736556.html
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。