1934: [Shoi2007]Vote 善意的投票
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1689 Solved: 1041
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
1 0 0
1 2
1 3
3 2
Sample Output
HINT
在第一个例子中,所有小朋友都投赞成票就能得到最优解
解题思路:我终于找到打最小割的正确姿势了。不多讲,简单建图,最大流。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,len=1,ans;
int to[100000],next[100000],zhi[100000];
int h[310],dis[310];
int q[100000];
inline int read()
{
char y;int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void insert(int x,int y,int z)
{
++len;
to[len]=y; next[len]=h[x]; h[x]=len; zhi[len]=z;
}
bool bfs()
{
memset(dis,-1,sizeof(dis)); dis[0]=0;
int tail=0,head=0; ++tail; q[tail]=0;
while (head<tail)
{
++head;
int u=h[q[head]];
while (u!=0)
{
if (dis[to[u]]==-1 && zhi[u]>0)
{
dis[to[u]]=dis[q[head]]+1;
++tail; q[tail]=to[u];
}
u=next[u];
}
}
if (dis[n+1]!=-1) return true;else return false;
}
int dicnic(int sum,int now)
{
if (now==n+1) return sum;
int sug=0;
int u=h[now];
while (u!=0)
{
if (zhi[u]>0 && dis[to[u]]==dis[now]+1)
{
int s=dicnic(min(sum-sug,zhi[u]),to[u]);
sug+=s; zhi[u]-=s; zhi[u^1]+=s;
if (sug==sum) return sug;
}
u=next[u];
}
if (sug==0) dis[now]=-1;
return sug;
}
int main()
{
n=read(); m=read();
for (int i=1;i<=n;++i)
{
int x; x=read();
if (x==1)
{
insert(0,i,1); insert(i,0,0);
insert(i,n+1,0); insert(n+1,i,0);
}else
{
insert(0,i,0); insert(i,0,0);
insert(i,n+1,1); insert(n+1,i,0);
}
}
for (int i=1;i<=m;++i)
{
int x,y;
x=read(); y=read();
insert(x,y,1); insert(y,x,1);
}
ans=0;
while (bfs())
{
ans+=dicnic(0x7fffffff,0);
}
printf("%d",ans);
}