bzoj1934: [Shoi2007]Vote 善意的投票(显然最小割)
1934: [Shoi2007]Vote 善意的投票
题目:传送门
题解:
明显的不能再明显的最小割。。。
st连同意的,不同意的连ed
朋友之间两两连边(即双向边)
流量都为1...
为啥:
一个人只有两种选择...同意or不同意
那么如果选择违背了个人意愿那么肯定要割掉一条边(起冲突了嘛),那就是流量啊...
如果当前选择让两个盆友不在同一集合,那就产生了冲突,还是要割,还是流量啊...
一A美滋滋~
代码水一发:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define qread(x) x=read() 7 using namespace std; 8 inline int read() 9 { 10 int f=1,x=0;char ch; 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return f*x; 14 } 15 struct node 16 { 17 int x,y,c,next,other; 18 }a[210000];int len,last[110000]; 19 int n,m,st,ed; 20 void ins(int x,int y,int c) 21 { 22 int k1,k2; 23 k1=++len; 24 a[len].x=x;a[len].y=y;a[len].c=c; 25 a[len].next=last[x];last[x]=len; 26 27 k2=++len; 28 a[len].x=y;a[len].y=x;a[len].c=0; 29 a[len].next=last[y];last[y]=len; 30 31 a[k1].other=k2; 32 a[k2].other=k1; 33 } 34 int list[110000],h[110000],head,tail; 35 bool bt_h() 36 { 37 memset(h,0,sizeof(h));h[st]=1; 38 list[1]=st;head=1;tail=2; 39 while(head!=tail) 40 { 41 int x=list[head]; 42 for(int k=last[x];k;k=a[k].next) 43 { 44 int y=a[k].y; 45 if(h[y]==0 && a[k].c>0) 46 { 47 h[y]=h[x]+1; 48 list[tail++]=y; 49 } 50 } 51 head++; 52 } 53 if(h[ed]>0)return true; 54 return false; 55 } 56 int find_flow(int x,int flow) 57 { 58 if(x==ed)return flow; 59 int s=0,t; 60 for(int k=last[x];k;k=a[k].next) 61 { 62 int y=a[k].y; 63 if(h[y]==h[x]+1 && a[k].c>0 && s<flow) 64 { 65 s+=t=find_flow(y,min(a[k].c,flow-s)); 66 a[k].c-=t;a[a[k].other].c+=t; 67 } 68 } 69 if(s==0)h[x]=0; 70 return s; 71 } 72 int main() 73 { 74 qread(n);qread(m); 75 len=0;memset(last,0,sizeof(last)); 76 st=110000-2;ed=st+1; 77 for(int i=1;i<=n;i++) 78 { 79 int x;qread(x); 80 if(x==1)ins(st,i,1); 81 else ins(i,ed,1); 82 } 83 for(int i=1;i<=m;i++) 84 { 85 int x,y; 86 qread(x);qread(y); 87 ins(x,y,1); 88 ins(y,x,1); 89 } 90 int ans=0; 91 while(bt_h())ans+=find_flow(st,999999999); 92 printf("%d\n",ans); 93 return 0; 94 }