幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?
标签:
Time Limit: 1 Sec
Memory Limit: 256 MB
幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?
只需要输出一个整数,即可能的最小冲突数
3 3
1 0 0
1 2
1 3
3 2
题意
题解:
网络流最小割
S连同意的,T连不同意的
然后朋友相互连接
代码:
#include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; const int Ni = 100210; const int MAX = 1<<26; struct Edge{ int u,v,c; int next; }edge[20*Ni]; int n,m; int edn;//边数 int p[Ni];//父亲 int d[Ni]; int sp,tp;//原点,汇点 void addedge(int u,int v,int c) { edge[edn].u=u; edge[edn].v=v; edge[edn].c=c; edge[edn].next=p[u]; p[u]=edn++; edge[edn].u=v; edge[edn].v=u; edge[edn].c=0; edge[edn].next=p[v]; p[v]=edn++; } int bfs() { queue <int> q; memset(d,-1,sizeof(d)); d[sp]=0; q.push(sp); while(!q.empty()) { int cur=q.front(); q.pop(); for(int i=p[cur];i!=-1;i=edge[i].next) { int u=edge[i].v; if(d[u]==-1 && edge[i].c>0) { d[u]=d[cur]+1; q.push(u); } } } return d[tp] != -1; } int dfs(int a,int b) { int r=0; if(a==tp)return b; for(int i=p[a];i!=-1 && r<b;i=edge[i].next) { int u=edge[i].v; if(edge[i].c>0 && d[u]==d[a]+1) { int x=min(edge[i].c,b-r); x=dfs(u,x); r+=x; edge[i].c-=x; edge[i^1].c+=x; } } if(!r)d[a]=-2; return r; } int dinic(int sp,int tp) { int total=0,t; while(bfs()) { while(t=dfs(sp,MAX)) total+=t; } return total; } int main() { int i,u,v,c; while(~scanf("%d%d",&n,&m)) { edn=0;//初始化 memset(p,-1,sizeof(p)); sp=0;tp=n+1; for(int i=1;i<=n;i++) { int x; scanf("%d",&x); if(x)addedge(sp,i,1); else addedge(i,tp,1); } for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y,1); addedge(y,x,1); } printf("%d\n",dinic(sp,tp)); } return 0; }
BZOJ 1934: [Shoi2007]Vote 善意的投票 最小割
标签:
原文地址:http://www.cnblogs.com/qscqesze/p/4790080.html