题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1934
求图的最小割=求一下图的最大流。
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int cap[305][305],level[305],vis[305],a[305];
int maxFlow,minFlow,minFlowNode;
int N,M; ///人数和关系数。
int S,T; ///S表示赞成,T表示反对
bool bfs() ///对图的节点进行分层
{
queue<int>qu;
memset(level,-1,sizeof(level));
level[S] = 0;
qu.push(S);
while(!qu.empty())
{
int u = qu.front();
qu.pop();
for(int i = 0; i <= T; i++)
{
if(level[i] == -1 && cap[u][i]>0)
{
level[i] = level[u] + 1;
if(i == T)
return true;
qu.push(i);
}
}
}
return false;
}
void dfs()
{
int u,v,cur,i;
deque<int>qu; ///双端队列,可以当作栈来用
memset(vis,0,sizeof(vis));
vis[S] = 1;
qu.push_back(S);
while(!qu.empty())
{
cur = qu.back();
if(cur == T)
{
minFlow = INF+1;
minFlowNode = S;
for(i = 1; i < qu.size(); i++)
{
u = qu[i-1];
v = qu[i];
if(cap[u][v]>0 && minFlow>cap[u][v])
{
minFlow = cap[u][v];
minFlowNode = u;
}
}
maxFlow += minFlow;
for(i = 1; i < qu.size(); i++)
{
u = qu[i-1];
v = qu[i];
cap[u][v] -= minFlow;
cap[v][u] += minFlow;
}
while(!qu.empty() && qu.back() != minFlowNode)
{
vis[qu.back()] = 0;
qu.pop_back();
}
}
else
{
for(i = 1; i <= T; i++)
{
if(cap[cur][i] > 0 && level[i]==level[cur]+1 && vis[i]==0)
{
vis[i] = 1;
qu.push_back(i);
break;
}
}
if(i > T)
qu.pop_back();
}
}
}
void dinic()
{
maxFlow = 0;
while(bfs())
{
dfs();
}
}
int main()
{
while(~scanf("%d%d",&N,&M))
{
memset(cap,0,sizeof(cap));
int x,y;
S = 0;
T = N+1;
for(int i = 1; i <= N; i++)
{
scanf("%d",&x);
if(x == 1)
cap[S][i] = 1;
else
cap[i][T] = 1;
}
for(int i = 1; i <= M; i++)
{
scanf("%d%d",&x,&y);
cap[x][y] = cap[y][x] = 1;
}
dinic();
printf("%d\n",maxFlow);
}
return 0;
}