【0521模拟赛】小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
#include
#include
#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;
}
 

 

转载于:https://www.cnblogs.com/PaperCloud/p/6906220.html

你可能感兴趣的:(【0521模拟赛】小Z爱划水)