首页 > 代码库 > BZOJ-2768: [JLOI2010]冠军调查(超级裸的最小割)

BZOJ-2768: [JLOI2010]冠军调查(超级裸的最小割)

2768: [JLOI2010]冠军调查

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段。随着卫冕冠军巴萨罗那的淘汰,英超劲旅切尔西成为了头号热门。新浪体育最近在吉林教育学院进行了一次大规模的调查,调查的内容就是关于切尔西能否在今年问鼎欧洲冠军。新浪体育的记者从各个院系中一共抽取了n位同学作为参与者,大家齐聚一堂,各抒己见。每一位参与者都将发言,阐述自己的看法。参与者的心里都有一个看法,比如FireDancer认为切尔西不可能夺冠,而WaterDancer认为切尔西一定问鼎。但是因为WaterDancer是FireDancer的好朋友,所以可能FireDancer为了迁就自己的好朋友,会在发言中支持切尔西。也就是说每个参与者发言时阐述的看法不一定就是心里所想的。现在告诉你大家心里的想法和参与者的朋友网,希望你能安排每个人的发言内容,使得违心说话的人的总数与发言时立场不同的朋友(对)的总数的和最小。
 

Input

第一行两个整数n和m,其中n(2≤n≤300)表示参与者的总数,m(0≤m≤n(n-1)/2)表示朋友的总对数。
第二行n个整数,要么是0要么是1。如果第i个整数的值是0的话,表示第i个人心里认为切尔西将与冠军无缘,如果是1的话,表示他心里认为切尔西必将夺魁。
下面m行每行两个不同的整数,i和j(1≤i, j≤n)表示i和j是朋友。注意没有一对朋友会在输入中重复出现。朋友关系是双向的,并且不会传递。
 

Output

 
只有一个整数,为最小的和。

Sample Input

3 3
1 0 0
1 2
1 3
2 3

Sample Output

1

HINT

 

最好的安排是所有人都在发言时说切尔西不会夺冠。这样没有一对朋友的立场相左,只有第1个人他违心说了话。

 

最小割不解释。

/**************************************************************    Problem: 2768    User: winmt    Language: C++    Result: Accepted    Time:32 ms    Memory:3064 kb****************************************************************/ #include<iostream>#include<fstream>#include<cstdio>#include<algorithm>#include<string>#include<vector>#include<queue>#include<deque>#include<utility>#include<map>#include<set>#include<cmath>#include<cstdlib>#include<ctime>#include<functional>#include<sstream>#include<cstring>#include<bitset>#include<stack>using namespace std; int n,m,s,t,cnt=1,x,y,z;struct sdt{    int cap,flow,u,v;}e[90305];int nxt[90305],fir[305],d[305],par[305],num[305],cur[305];bool vis[305]; int read(){    int x=0;char c=getchar();    while(c<48||c>57)c=getchar();    while(c>47&&c<58)x*=10,x+=c-48,c=getchar();    return x;} void add(int u,int v,int cp,int fl){    e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=cp;e[cnt].flow=fl;    nxt[cnt]=fir[u];fir[u]=cnt;} void bfs(){    //memset(vis,0,sizeof(vis));    //memset(d,0,sizeof(d));    queue<int>q;    d[t]=0;    vis[t]=1;    q.push(t);    while(!q.empty())    {        int k=q.front();        q.pop();        for(int i=fir[k];i;i=nxt[i])        {            if(!vis[e[i].v] && e[i].cap==0)            {                vis[e[i].v]=1;                d[e[i].v]=d[k]+1;                q.push(e[i].v);            }        }    }} int agument(){    int p=t;    int ans=2147483647;    while(p!=s)    {        ans=min(ans,e[par[p]].cap-e[par[p]].flow);        p=e[par[p]].u;    }    p=t;    while(p!=s)    {        e[par[p]].flow+=ans;        e[par[p]^1].flow-=ans;        p=e[par[p]].u;    }    return ans;} int isap(){    //memset(num,0,sizeof(num));    int flow=0;    for(int i=1;i<=t;i++)    {        num[d[i]]++;        cur[i]=fir[i];    }    int p=s;    while(d[s]<t)    {        if(p==t)        {            flow+=agument();            p=s;        }        bool ok=0;        for(int i=cur[p];i;i=nxt[i])        {            if(e[i].cap>e[i].flow && d[p]==d[e[i].v]+1)            {                  ok=1;                  par[e[i].v]=i;                  cur[p]=i;                  p=e[i].v;                  break;              }          }        if(!ok)        {            int mn=t-1;            for(int i=fir[p];i;i=nxt[i])            {                if(e[i].cap>e[i].flow)mn=min(mn,d[e[i].v]);            }            if(--num[d[p]]==0)break;            num[d[p]=mn+1]++;            cur[p]=fir[p];            if(p!=s)p=e[par[p]].u;        }    }    return flow;} int main(){    n=read();m=read();    //memset(nxt,0,sizeof(nxt));    //memset(fir,0,sizeof(fir));    s=1;    t=n+2;    for(int i=1;i<=n;i++)    {        z=read();        if(z)        {            add(s,i+1,1,0);            add(i+1,s,0,0);        }        else        {            add(i+1,t,1,0);            add(t,i+1,1,0);        }    }    for(int i=1;i<=m;i++)    {        x=read();y=read();        add(1+x,1+y,1,0);        add(y+1,x+1,1,0);    }    bfs();    printf("%d\n",isap());    return 0;}

  

BZOJ-2768: [JLOI2010]冠军调查(超级裸的最小割)