1934: [Shoi2007]Vote 善意的投票 (网络流)

来源:互联网 发布:大数据人才的薪资待遇 编辑:程序博客网 时间:2024/06/06 20:24

1934: [Shoi2007]Vote 善意的投票

如果把每个人都看做一个节点,题意其实就是等价于求把点集划分为2个独立部分的最小代价;
我们把赞成的点都引向汇点一条流量为1的边;
从原点向反对的点都引一条流量为1的边;
每一对好友之间连一条容量为1的边;
那么最小代价就是从源到汇的最小割,而最小割==最大流;

#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>using namespace std;const int Mn = 300 + 10, Me = Mn * Mn * 2;int hd[Mn],nxt[Me],to[Me],f[Me],cnt;int step[Mn],que[Mn];int S,T;int n,m;inline void add(int x,int y,int z){to[cnt] = y;f[cnt] = z;nxt[cnt] = hd[x];hd[x] = cnt++;to[cnt] = x;f[cnt] = 0;nxt[cnt] = hd[x];hd[x] = cnt++;}inline int zeng(int x,int flow){if(x == T) return flow;int res(0);for(int i = hd[x];~i && res < flow; i = nxt[i])if(f[i] && step[to[i]] == step[x] + 1){int dt = zeng(to[i],min(flow - res,f[i]));f[i] -= dt,f[1^i] += dt,res += dt;}if(!res) step[x] = -1;return res;}inline bool check(){memset(step,-1,sizeof step);int h = 1 , t = 2;que[1] = S;step[S] = 0;while(h < t){int sta = que[h++];for(int i = hd[sta];~i; i = nxt[i])if(f[i] && step[to[i]] == -1){step[to[i]] = step[sta] + 1;que[t++] = to[i];}}return ~step[T];}inline int dinic(){int res(0);while(check()) res += zeng(S,0x7fffffff);return res;}int main(){memset(hd,-1,sizeof hd);scanf("%d%d",&n,&m);S = 0, T = n+1;for(int i = 1,x; i <= n; i++){scanf("%d",&x);if(x) add(S,i,1);else add(i,T,1);}for(int i = 1,x,y; i <= m; i++){scanf("%d%d",&x,&y);add(x,y,1);add(y,x,1);}printf("%d\n",dinic());return 0;} 




原创粉丝点击