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; }
时间: 2024-10-11 22:23:50