【刷题】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

HINT

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

Solution

源点向所有赞成睡觉的人连边,容量为 \(1\) ,不赞成睡觉的向汇点连边,容量为 \(1\)
好朋友之间连双向边
那么最小割代表的就是用最小的代价完成投票

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=300+10,MAXM=MAXN*MAXN+10,inf=0x3f3f3f3f;
int n,m,e=1,beg[MAXN],cur[MAXN],level[MAXN],vis[MAXN],clk,s,t,to[MAXM<<1],nex[MAXM<<1],cap[MAXM<<1];
std::queue<int> q;
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y,int z)
{
	to[++e]=y;
	nex[e]=beg[x];
	beg[x]=e;
	cap[e]=z;
	to[++e]=x;
	nex[e]=beg[y];
	beg[y]=e;
	cap[e]=0;
}
inline bool bfs()
{
	memset(level,0,sizeof(level));
	level[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		for(register int i=beg[x];i;i=nex[i])
			if(cap[i]&&!level[to[i]])level[to[i]]=level[x]+1,q.push(to[i]);
	}
	return level[t];
}
inline int dfs(int x,int maxflow)
{
	if(x==t||!maxflow)return maxflow;
	vis[x]=clk;
	int res=0;
	for(register int &i=cur[x];i;i=nex[i])
		if((vis[x]^vis[to[i]])&&cap[i]&&level[to[i]]==level[x]+1)
		{
			int f=dfs(to[i],min(cap[i],maxflow));
			res+=f;
			cap[i]-=f;
			cap[i^1]+=f;
			maxflow-=f;
			if(!maxflow)break;
		}
	return res;
}
inline int Dinic()
{
	int res=0;
	while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf);
	return res;
}
int main()
{
	read(n);read(m);
	s=n+1,t=s+1;
	for(register int i=1;i<=n;++i)
	{
		int opt;read(opt);
		if(opt)insert(s,i,1);
		else insert(i,t,1);
	}
	for(register int i=1;i<=m;++i)
	{
		int u,v;read(u);read(v);
		insert(u,v,1);insert(v,u,1);
	}
	write(Dinic(),'\n');
	return 0;
}
posted @ 2018-08-04 09:48  HYJ_cnyali  阅读(147)  评论(0编辑  收藏  举报