BZOJ 1934 善意的投票

Posted on 2016-03-27 17:10  ziliuziliu  阅读(154)  评论(0编辑  收藏  举报

一个最小割模型吧。。。。1连源,0连汇,朋友之间互相连,最小割等于最大流。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxv 650
#define maxe 200500
#define inf 1000000007
using namespace std;
struct edge
{
    int v,f,nxt;
}e[maxe];
int n,m,s,t,g[maxv],x,y,nume=1,dis[maxv];
bool vis[maxv];
queue <int> q;
void addedge(int u,int v,int f)
{
    e[++nume].v=v;
    e[nume].f=f;
    e[nume].nxt=g[u];
    g[u]=nume;
    e[++nume].v=u;
    e[nume].f=0;
    e[nume].nxt=g[v];
    g[v]=nume;
}
bool bfs()
{
    while (!q.empty()) 
        q.pop();
    memset(vis,false,sizeof(vis));
    memset(dis,-1,sizeof(dis));
    q.push(s);vis[s]=true;dis[s]=0;
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((vis[v]==false) && (e[i].f))
            {
                dis[v]=dis[head]+1;
                vis[v]=true;
                q.push(v);
            }
        }
    }
    if (dis[t]==-1) return false;
    return true;
}
int dinic(int x,int low)
{
    if (x==t) return low;
    else
    {
        int ret=0;
        for (int i=g[x];low && i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((e[i].f) && (dis[v]==dis[x]+1))
            {
                int dd=dinic(v,min(low,e[i].f));
                ret=ret+dd;low=low-dd;
                e[i].f=e[i].f-dd;e[i^1].f=e[i^1].f+dd;
            }
        }
        if (ret==0) dis[x]=-1;
        return ret;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    s=0;t=2*n+1;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if (x==1) addedge(s,i,1);
        else addedge(i+n,t,1);
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y+n,1);
        addedge(y,x+n,1);
    }
    int min_cut=0;
    while (bfs())
        min_cut+=dinic(s,inf);
    printf("%d\n",min_cut);
    return 0;
}