题目描述
小Z和其它机房同学都面临一个艰难的抉择,那就是 要不要划水?
每个人都有自己的一个意见,有的人想做题,有的人想划水。
当然,每个人只能选择一个事情做。如果一个人做的事情和他想做的不同,那么他会产生1不满意度。
更棘手的是,他们之间一些人是朋友,如果两人是朋友,但是他们做的事情不同,那么会有1不满意度产生。
小Z不想看到大家闹得不高兴,他想知道,不满意度最小能是多少?
输入输出格式
输入格式:
第一行两个数字n,m 分别表示有n个人和m对朋友关系
第二行n个0/1,1表示想做题,0表示想划水。
然后是m行,每行两个数字a,b 表示a和b是朋友
输出格式:
输出只包含一个数字,表示最小的不满意度。
解析:
考虑最小割
如果一个选项是1,从S向它连流量1的边,
否则从它向T连流量1的边.
每对关系之间互相连流量1的边.
然后跑一遍最大流求它的最小割......
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define S 0
#define T 301
#define INF 2000000000
using namespace std;
inline int read(){
int x = ,f = ; char ch = getchar();
while(ch < ''||ch > '') {if(ch == '-') f =-; ch = getchar();}
while(ch >=''&&ch <='') {x = x*+ch-''; ch = getchar();}
return x * f;
}
int n,m,q[T+],top=,head[T+],d[T+],cnt=,ans=;
struct edge{int to,next,w;}e[T*T*+];
void ins(int f,int t,int w){
e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
e[++cnt]=(edge){f,head[t],};head[t]=cnt;
}
int dfs(int x,int f){
if(x==T) return f;
int used=;
for(int i=head[x];i;i=e[i].next)
if(e[i].w&&d[e[i].to]==d[x]+){
int w=dfs(e[i].to,min(f-used,e[i].w));
used+=w; e[i].w-=w; e[i^].w+=w;
if(used==f) return f;
}
return d[x]=-,used;
}
bool bfs(){
memset(d,,sizeof(d)); int i,j;
for(d[q[top=i=]=S]=;i<=top;++i)
for(j=head[q[i]];j;j=e[j].next)
if(e[j].w&&!d[e[j].to])
d[q[++top]=e[j].to]=d[q[i]]+;
return d[T];
}
int main(){
n=read(); m=read();
for(int i=;i<=n;i++) read()?ins(S,i,):ins(i,T,);
int x,y;
for(int i=;i<=m;i++){
x=read(); y=read();
ins(x,y,); ins(y,x,);
}
while(bfs()) ans+=dfs(S,INF);
printf("%d\n", ans);
return ;
}