BZOJ传送门
Time Limit: 1 Sec Memory Limit: 64 MB
Submit: 1721 Solved: 1061
[Submit][Status][Discuss]
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
Sol:
设置源点汇点,将每个支持的小朋友连源点,容量为1,每个反对的小朋友连汇点,容量为1
将每对小朋友互相连起来,跑最大流就是答案
因为最大流=最小割,就是分成支持和反对的两方,中间个点的边就是违背本心的小朋友
#include
#include
#include
#include
#include
using namespace std;
#define N 305
#define M N*N*4
struct NetWork{
struct Edge{int fr,to,flow;}edge[M];
vector<int> g[N];
int cnt,n,m,s,t,flow;int d[N],p[N],num[N],cur[N];
void Add_Edge(int fr,int to,int fl){
edge[cnt++]=(Edge){fr,to,fl};edge[cnt++]=(Edge){to,fr,0};
g[fr].push_back(cnt-2),g[to].push_back(cnt-1);
}
bool bfs(){
memset(d,-1,sizeof(d));queue<int> q;q.push(s);d[s]=0;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0,lim=g[x].size();iif(e.flow>0&&d[e.to]==-1) d[e.to]=d[x]+1,q.push(e.to);
}
}
return d[t]!=-1;
}
void MaxFlow(){
while(bfs()){
memset(cur,0,sizeof(cur));int k=0,x=s;
for(;;){
if(x==t){
int mine=-1,minf=0x7fffffff;
for(int i=0;iif(edge[p[i]].flowfor(int i=0;i1].flow+=minf;
flow+=minf,x=edge[p[mine]].fr,k=mine;
}
for(int &i=cur[x],lim=g[x].size();iif(e.flow>0&&d[x]+1==d[e.to]) break;
}
if(cur[x]else{
if(!k) break;
d[x]=-1,x=edge[p[--k]].fr;
}
}
}
}
inline int in(int x=0,char ch=getchar()){while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x;}
void init(){
int u,v;n=in(),m=in();s=0,t=n+1;
for(int i=1;i<=n;i++){
if(in()) Add_Edge(s,i,1);
else Add_Edge(i,t,1);
}
for(int i=1;i<=m;i++)
u=in(),v=in(),Add_Edge(u,v,1),Add_Edge(v,u,1);
MaxFlow();printf("%d\n",flow);
}
}s;
int main(){s.init();return 0;}