bzoj1934 [Shoi2007]Vote 善意的投票
来源:互联网 发布:js 日期转字符串 编辑:程序博客网 时间:2024/06/07 18:27
(http://www.elijahqi.win/2017/12/25/bzoj1934-shoi2007vote-%E5%96%84%E6%84%8F%E7%9A%84%E6%8A%95%E7%A5%A8/)
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
Sample Output
1
HINT
在第一个例子中,所有小朋友都投赞成票就能得到最优解
Source
Day2
建模好难%%icefox 他真的太大佬了qwq
如果睡觉从源向他建边 如果不睡觉从他向汇建边 如果互相是好友 则互相建边 所有边的权值都是1 然后跑最大流 最小割 即可 因为割掉0~i或者i~t的边表示违背自己的意愿 如果割掉互相之间的边 表示为和好友产生了冲突
#include<queue>#include<cstdio>#include<cstring>#include<algorithm>#define inf 0x3f3f3f3f#define N 330using namespace std;inline char gc(){ static char now[1<<16],*S,*T; if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++;}inline int read(){ int x=0;char ch=gc(); while(ch<'0'||ch>'9') ch=gc(); while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();} return x;}int num=1,level[N],h[N],n,m,T;struct node{ int y,z,next;}data[N*N]; inline void insert1(int x,int y,int z){ data[++num].y=y;data[num].z=z;data[num].next=h[x];h[x]=num; data[++num].y=x;data[num].z=0;data[num].next=h[y];h[y]=num;}inline bool bfs(){ memset(level,0,sizeof(level));level[0]=1;queue<int>q;q.push(0); while(!q.empty()){ int x=q.front();q.pop(); for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if (level[y]||!z) continue;level[y]=level[x]+1;q.push(y);if (y==T) return 1; } }return 0;}inline int dfs(int x,int s){ if (x==T) return s;int ss=s; for (int i=h[x];i;i=data[i].next){ int y=data[i].y,z=data[i].z; if (level[x]+1==level[y]&&z){ int xx=dfs(y,min(s,z));if (!xx) level[y]=0;s-=xx; data[i].z-=xx;data[i^1].z+=xx;if (!s) return ss; } }return ss-s;} int main(){ freopen("bzoj1934.in","r",stdin); n=read();m=read();T=n+1; for (int i=1;i<=n;++i){int x=read();if (x) insert1(0,i,1);else insert1(i,T,1);} for (int i=1;i<=m;++i){ int x=read(),y=read();insert1(x,y,1);insert1(y,x,1); }int ans=0; while(bfs()) ans+=dfs(0,inf); printf("%d",ans); return 0;}