题目描述
小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 = 0,f = 1; char ch = getchar(); while(ch < '0'||ch > '9') {if(ch == '-') f =-1; ch = getchar();} while(ch >='0'&&ch <='9') {x = x*10+ch-'0'; ch = getchar();} return x * f; } int n,m,q[T+5],top=0,head[T+5],d[T+5],cnt=1,ans=0; struct edge{int to,next,w;}e[T*T*10+5]; void ins(int f,int t,int w){ e[++cnt]=(edge){t,head[f],w};head[f]=cnt; e[++cnt]=(edge){f,head[t],0};head[t]=cnt; } int dfs(int x,int f){ if(x==T) return f; int used=0; for(int i=head[x];i;i=e[i].next) if(e[i].w&&d[e[i].to]==d[x]+1){ int w=dfs(e[i].to,min(f-used,e[i].w)); used+=w; e[i].w-=w; e[i^1].w+=w; if(used==f) return f; } return d[x]=-1,used; } bool bfs(){ memset(d,0,sizeof(d)); int i,j; for(d[q[top=i=1]=S]=1;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]]+1; return d[T]; } int main(){ n=read(); m=read(); for(int i=1;i<=n;i++) read()?ins(S,i,1):ins(i,T,1); int x,y; for(int i=1;i<=m;i++){ x=read(); y=read(); ins(x,y,1); ins(y,x,1); } while(bfs()) ans+=dfs(S,INF); printf("%d ", ans); return 0; }