BZOJ_1934_[Shoi2007]Vote 善意的投票

BZOJ_1934_[Shoi2007]Vote 善意的投票

Description

幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

Input

第一行只有两个整数n,m,保证有2≤n≤300,1≤m≤n(n-1)/2。其中n代表总人数,m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示同意睡觉,当它为0时表示反对睡觉。接下来文件还有m行,每行有两个整数i,j。表示i,j是一对好朋友,我们保证任何两对i,j不会重复。

Output

只需要输出一个整数,即可能的最小冲突数。

Sample Input

3 3
1 0 0
1 2
1 3
3 2

Sample Output

1
 

设源点S,汇点T,S向意愿为1的人连边,意愿为0的人向T连边。
割这些边表示投意愿相反的票。
每个人向朋友连边,割这些边表示和朋友发生冲突。
求最小割即可。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define inf 100000000
#define S (n+1)
#define T (n+2)
#define N 350
#define M 500050
int head[N],to[M],nxt[M],flow[M],cnt=1,n,m,dep[N];
int Q[N],l,r;
inline void add(int u,int v,int f) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
}
bool bfs() {
int i;
memset(dep,0,sizeof(dep));
dep[S]=1;
l=r=0;
Q[r++]=S;
while(l<r) {
int x=Q[l++];
for(i=head[x];i;i=nxt[i]) {
if(!dep[to[i]]&&flow[i]) {
dep[to[i]]=dep[x]+1;
if(to[i]==T) return 1;
Q[r++]=to[i];
}
}
}
return 0;
}
int dfs(int x,int mf) {
if(x==T) return mf;
int nf=0,i;
for(i=head[x];i;i=nxt[i]) {
if(dep[to[i]]==dep[x]+1&&flow[i]) {
int tmp=dfs(to[i],min(mf-nf,flow[i]));
nf+=tmp;
flow[i]-=tmp;
flow[i^1]+=tmp;
if(nf==mf) break;
}
}
dep[x]=0;
return nf;
}
void dinic() {
int ans=0,f;
while(bfs())while(f=dfs(S,inf))ans+=f;
printf("%d\n",ans);
}
int main() {
scanf("%d%d",&n,&m);
int i,x,y;
for(i=1;i<=n;i++) {
scanf("%d",&x);
if(x) add(S,i,1);
else add(i,T,1);
}
for(i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
add(x,y,1);
add(y,x,1);
}
dinic();
}
上一篇:Mssql 行转列


下一篇:IWorkSpace接口介绍 1.打开各种数据库