您的位置:首页 > 其它

【BZOJ 1934】 [Shoi2007]Vote 善意的投票

2016-02-15 07:26 316 查看

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

HINT

在第一个例子中,所有小朋友都投赞成票就能得到最优解

做的时候随便搞了搞套了个板子就A了
事后想了想这样好像是对的
对于每个人来说,如果他同意就向S连一条容量为1的边,向T连一条容量为0的边,反对就相反
是好朋友的小朋友之间互相连边,容量均为1,求出最小割,就是答案
因为每一个人要么是同意,要么反对,只能选一个,选违背自己的意愿要付出代价,即流量。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int inf=100000000,N=310;
struct ee{int to,next,f;}e[N*N*2];
int head
,q[N*2],dis
,x
;
int S,T,n,m,cnt=1,ans,w;

void ins(int u,int v,int f){
e[++cnt].to=v;e[cnt].f=f;e[cnt].next=head[u];head[u]=cnt;
e[++cnt].to=u;e[cnt].f=0;e[cnt].next=head[v];head[v]=cnt;
}

bool bfs(){
for (int i=1;i<=T;i++) dis[i]=inf;
int h=0,t=1,now;
q[1]=S;dis[S]=0;
while(h!=t){
now=q[++h];
for (int i=head[now];i;i=e[i].next){
int v=e[i].to;
if (e[i].f&&dis[now]+1<dis[v]){
dis[v]=dis[now]+1;
if (v==T)return 1;
q[++t]=v;
}
}
}
if (dis[T]==inf) return 0; return 1;
}

int dinic(int now,int f){
if (now==T) return f;
int rest=f;
for (int i=head[now];i;i=e[i].next){
int v=e[i].to;
if (e[i].f&&dis[v]==dis[now]+1&&rest){
int t=dinic(v,min(rest,e[i].f));
if (!t) dis[v]=0;
e[i].f-=t;
e[i^1].f+=t;
rest-=t;
//if(t) printf("%d %d %d\n",now,v,e[i].f);
}
}
return f-rest;
}
int main(){
scanf("%d%d",&n,&m);
S=0,T=n+1;
for (int i=1;i<=n;i++) {
scanf("%d",&x[i]);
if (x[i]==0) ins(S,i,1),ins(i,T,0);
else ins(S,i,0),ins(i,T,1);
}
int u,v;
for (int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
ins(u,v,1);ins(v,u,1);
}
while (bfs()) ans+=dinic(S,inf);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: