洛谷P2057 善意的投票
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2057 善意的投票相关的知识,希望对你有一定的参考价值。
题目描述
幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。
我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?
输入输出格式
输入格式:
文件的第一行只有两个整数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不会重复。
输出格式:
只需要输出一个整数,即可能的最小冲突数。
输入输出样例
3 3 1 0 0 1 2 1 3 3 2
1
说明
2≤n≤300,1≤m≤n(n-1)/2。
最小割。
从源点S向所有赞成的人连边,从所有反对的人向汇点T连边,在朋友之间连边,容量均为1。
若边u,v有朋友冲突,解决冲突等于割一条边,若S-u或者v-T有违背意愿,也相当于割一条边,所以求最小割就是答案。
太久没写网络流了,还保留着邻接矩阵时代的习惯,在DFS参数中把v写成了i,错得太隐蔽导致看不出(其实是自己弱),白调了好久。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 const int mxn=120010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 13 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 14 return x*f; 15 } 16 struct edge{ 17 int v,nxt; 18 int f; 19 }e[mxn]; 20 int hd[mxn],mct=1; 21 void add_edge(int u,int v,int f){ 22 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=f;hd[u]=mct; 23 e[++mct].v=u;e[mct].nxt=hd[v];e[mct].f=-f;hd[v]=mct; 24 return; 25 } 26 int n,m; 27 int S,T; 28 int dep[mxn]; 29 bool BFS(){ 30 queue<int>q; 31 q.push(S); 32 dep[S]=1; 33 while(!q.empty()){ 34 int u=q.front();q.pop(); 35 for(int i=hd[u];i;i=e[i].nxt){ 36 int v=e[i].v; 37 if(!dep[v] && e[i].f>0){ 38 dep[v]=dep[u]+1; 39 q.push(v); 40 if(v==T)return 1; 41 42 } 43 } 44 } 45 return 0; 46 } 47 int DFS(int u,int flow){ 48 if(u==T)return flow; 49 int i,tmp; 50 for(i=hd[u];i;i=e[i].nxt){ 51 int v=e[i].v; 52 if(dep[v]==dep[u]+1 && e[i].f>0){ 53 if(tmp=DFS(v,min(flow,e[i].f))){ 54 e[i].f-=tmp; 55 e[i^1].f+=tmp; 56 return tmp; 57 } 58 } 59 } 60 return 0; 61 } 62 void dinic(){ 63 int ans=0; 64 int flow=0; 65 while(BFS()){ 66 while(flow=DFS(S,1e9)){ 67 ans+=flow; 68 } 69 } 70 printf("%d\n",ans); 71 return; 72 } 73 int main(){ 74 n=read();m=read(); 75 int i,j; 76 S=0;T=n+1; 77 int u,v,w; 78 for(i=1;i<=n;i++){ 79 w=read(); 80 if(w)add_edge(S,i,1); 81 else add_edge(i,T,1); 82 } 83 for(i=1;i<=m;i++){ 84 u=read();v=read(); 85 add_edge(u,v,1); 86 add_edge(v,u,1); 87 } 88 dinic(); 89 return 0; 90 }
以上是关于洛谷P2057 善意的投票的主要内容,如果未能解决你的问题,请参考以下文章
P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查