【BZOJ1934】善意的投票(网络流)

题面

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

在第一个例子中,所有小朋友都投赞成票就能得到最优解

题解

每个小朋友投同意或者反对

相当于把小朋友们割为两块

那么,考虑最小割

首先,分别将同意和反对的与源点或者汇点连边

如果违反自己意愿,则相当于与这个点割开

同时,每个点与自己的朋友连边

如果割开,相当于与朋友意见不同

最后解决最小割,即求最大流

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 500
#define MAXL 200000
#define INF 20000000
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line
{
int v,next,w;
}e[MAXL];
int h[MAX],cnt;
int ans,S,T,n,m;
inline void Add(int u,int v,int w)
{
e[cnt]=(Line){v,h[u],w};
h[u]=cnt++;
e[cnt]=(Line){u,h[v],0};
h[v]=cnt++;
}
int level[MAX];
int cur[MAX];
bool BFS()
{
memset(level,0,sizeof(level));
level[S]=1;
queue<int> Q;
Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=h[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w&&!level[v])
level[v]=level[u]+1,Q.push(v);
}
}
return level[T];
}
int DFS(int u,int flow)
{
if(flow==0||u==T)return flow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w&&level[v]==level[u]+1)
{
int dd=DFS(v,min(flow,e[i].w));
flow-=dd;ret+=dd;
e[i].w-=dd;e[i^1].w+=dd;
}
}
return ret;
}
int Dinic()
{
int ret=0;
while(BFS())
{
for(int i=S;i<=T;++i)cur[i]=h[i];
ret+=DFS(S,INF);
}
return ret;
}
int main()
{
memset(h,-1,sizeof(h));
n=read();m=read();
S=0,T=n+1;
for(int i=1;i<=n;++i)
{
int k=read();
if(k)Add(S,i,1);
else Add(i,T,1);
}
for(int i=1;i<=m;++i)
{
int u=read(),v=read();
Add(u,v,1);Add(v,u,1);
}
printf("%d\n",Dinic());
return 0;
}

最新文章

  1. JavaScript模仿块级作用域
  2. jQuery EasyUI:根据数据库内容生成适合于easyui-tree的JSON数据格式
  3. OAF_开发系列06_实现OAF属性集的介绍和开发Attribute Set(案例)
  4. JQuery实现的模块交换动画效果
  5. 如何自己编写Makefile
  6. java提高篇(二十)-----集合大家族
  7. Activemq消息持久化
  8. nginx平滑重启与平滑升级的方法
  9. 关于SQL\SQL Server的三值逻辑简析
  10. HTML5新增的一些属性和功能之一
  11. cocos2d-x游戏开发(十五)游戏加载动画loading界面
  12. OGG数据仓库以及单向复制(一)
  13. Jetbrains Idea连接TFS时配置的坑
  14. 【组合数】微信群 @upcexam6016
  15. 上拉加载下拉刷新控件WaterRefreshLoadMoreView
  16. 20165318 2017-2018-2 《Java程序设计》第二周学习总结
  17. Jquery EasyUI 各组件属性、事件详解
  18. 基于JEECG的代码模板自动生成
  19. C#成员设计建议
  20. NDK下vfork+execl启动程序

热门文章

  1. RabbitMQ 简单测试
  2. CometD的消息推送
  3. NOIP 总结
  4. [bzoj3875] [Ahoi2014]骑士游戏
  5. centos 6.* 配置端口
  6. python入门学习笔记(三)
  7. hibernate之实体@onetomany和@manytoone双向注解(转)
  8. Java经典编程题50道之十四
  9. 变态的IE
  10. hdu1006 Tick and Tick