1934: [Shoi2007]Vote 善意的投票
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1796 Solved: 1094
[ Submit][ Status][ Discuss]
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
1 0 0
1 2
1 3
3 2
Sample Output
1
HINT
在第一个例子中,所有小朋友都投赞成票就能得到最优解
Source
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 3000
#define inf 1000000000
using namespace std;
int n,m;
int point[N],next[N],belong[N],tot=-1,u[N],remain[N];
int p[N],last[N],cnt,v[N],maxn,cnt1[N],num1[N],deep[N],laste[N],cur[N];
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
int addflow(int s,int t)
{
int now=t; int ans=inf;
while(now!=s)
{
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while(now!=s)
{
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
void bfs(int s,int t)
{
for (int i=s;i<=t;i++) deep[i]=t;
deep[t]=0;
queue<int> p; p.push(t);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]==t&&remain[i^1])
deep[v[i]]=deep[now]+1,p.push(v[i]);
}
}
int isap(int s,int t)
{
int maxflow=0;
bfs(s,t);
for (int i=s;i<=t;i++) cur[i]=point[i];
for (int i=s;i<=t;i++) num1[deep[i]]++;
int now=s;
while (deep[s]<t)
{
if (now==t)
{
maxflow+=addflow(s,t);
now=s;
}
int p=false;
for (int i=cur[now];i!=-1;i=next[i])
if (deep[v[i]]+1==deep[now]&&remain[i])
{
cur[now]=i;
p=true;
last[v[i]]=i;
now=v[i];
break;
}
if (!p)
{
int minn=t-1;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!--num1[deep[now]]) break;
deep[now]=minn+1;
num1[deep[now]]++;
cur[now]=point[now];
if (now!=s)
now=v[last[now]^1];
}
}
return maxflow;
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&belong[i]);
int num=2*n+2;
tot=-1;
memset(next,-1,sizeof(next));
memset(point,-1,sizeof(point));
for (int i=1;i<=n;i++)
{
if (!belong[i])
add(1,i+1,1);
else
add(i+n+1,num,1);
}
for (int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
if (belong[x]==belong[y]) continue;
if (!belong[x])
add(x+1,y+n+1,1);
else
add(y+1,x+n+1,1);
}
printf("%d\n",isap(1,num));
}