首页 > 代码库 > 【洛谷T4896】小Z爱划水
【洛谷T4896】小Z爱划水
题目描述
小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\n", ans);
return 0;
}
【洛谷T4896】小Z爱划水