最大流最小割定理说明和题目看这里
http://hihocoder.com/problemset/problem/1378
总结:
对于一个割(S,T),我们定义净流f(S,T)表示穿过割(S,T)的流量之和
任意一个割的净流f(S,T)总是和网络流的流量f相等
割的容量C(S,T)为所有从S到T的边容量之和
对于任一个网络流图来说,其最大流一定是小于等于最小割的
对于一个网络流图G=(V,E),其中有源点s和汇点t,那么下面三个条件是等价的: 1. 流f是图G的最大流 2. 残留网络Gf不存在增广路 3. 对于G的某一个割(S,T),此时f = C(S,T)
其实就是
割的容量 始终 >= 最大流,当割为残余网络的补图时等号成立
#include <bits/stdc++.h>
using namespace std;
#define maxn 10005
#define INF 1e9
struct node
{
int from,to,cap,flow;
node(int a,int b,int c,int d)
:from(a),to(b),cap(c),flow(d){}
};
vector<node>Edges;
vector<int>G[maxn];
bool vis[maxn];
int iter[maxn];
int level[maxn];
int N , M;
int S, T;
void add_edge(int from,int to,int cal)
{
Edges.push_back(node(from,to,cal,0));
Edges.push_back(node(to,from,0,0));
int size = Edges.size();
G[from].push_back(size-2);
G[to].push_back(size-1);
}
int ans[maxn];
int cnt;
bool BFS()
{
memset(vis,0,sizeof(vis));
level[S] = 1 ;
queue<int>Q;
Q.push(S);
vis[S] = 1;
while(!Q.empty())
{
int u = Q.front();
Q.pop();
// cout << u << endl;
// getchar();
for(int i = 0 ; i < G[u].size() ; ++i)
{
node &e = Edges[G[u][i]];
int v = e.to;
if( !vis[v] && e.flow < e.cap )
{
vis[v] = 1;
level[v] = level[u] + 1;
Q.push(v);
}
}
}
return vis[T];
}
int DFS(int u,int a)
{
if( u == T || a == 0 )
return a;
int f , flow = 0;
for(int &i = iter[u] ; i < G[u].size() ; ++i)
{
node &e = Edges[G[u][i]];
int v = e.to;
if( level[v] == level[u] + 1 && ( f = DFS(v,min(a,e.cap - e.flow) )) > 0 )
{
flow += f;
a -= f;
e.flow += f;
Edges[G[u][i]^1].flow -= f;
if( a == 0 )break;
}
}
return flow;
}
int Dinic()
{
int res = 0;
while( BFS() )
{
memset(iter,0,sizeof(iter));
res += DFS(S,INF);
}
return res;
}
int main()
{
cin >> N >> M;
S = 1 , T = N;
for(int i = 0 ; i < M ; ++i)
{
int a,b,c;
cin >> a >> b >> c;
add_edge(a,b,c);
}
cout << Dinic() << " ";
for(int i = 1 ; i <= N ; ++i)
{
if(vis[i])ans[cnt++] = i;
}
cout << cnt << endl;
for(int i =0 ;i < cnt ; ++i)
cout << ans[i] << " ";
}