题目

幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

输入格式

第一行只有两个整数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不会重复。

输出格式

只需要输出一个整数,即可能的最小冲突数。

输入样例

3 3

1 0 0

1 2

1 3

3 2

输出样例

1

解释

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

题解

我们设源汇点S、T,S向赞成的小朋友连边,不赞成的向T连边,好友之间互相连边,容量均为1

此时求最小割即为答案

对于任意一一对好友,他们要么在同一边,要么二者断开【好友冲突】,要么其中一者与源汇点断开【改变意愿】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
using namespace std;
const int maxn = 305,maxm = 300005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int h[maxn],ne = 0,N,M,d[maxn],vis[maxn],cur[maxn],S,T;
struct EDGE{int to,nxt,f;}ed[maxm];
inline void build(int u,int v,int w){
ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
}
bool bfs(){
queue<int> q;
for (int i = S; i <= T; i++) vis[i] = false,d[i] = INF;
d[S] = 0; q.push(S); int to,u;
while (!q.empty()){
u = q.front(); q.pop();
Redge(u) if (ed[k].f && !vis[to = ed[k].to]){
d[to] = d[u] + 1; vis[to] = true;
q.push(to);
}
}
return vis[T];
}
int dfs(int u,int minf){
if (u == T || !minf) return minf;
int flow = 0,f,to;
if (cur[u] == -2) cur[u] = h[u];
for (int& k = cur[u]; k != -1; k = ed[k].nxt)
if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
ed[k].f -= f; ed[k ^ 1].f += f;
flow += f; minf -= f;
if (!minf) break;
}
return flow;
}
int maxflow(){
int flow = 0;
while (bfs()){
fill(cur,cur + maxn,-2);
flow += dfs(S,INF);
}
return flow;
}
int main(){
memset(h,-1,sizeof(h));
N = RD(); M = RD(); S = 0; T = N + 1; int a,b;
REP(i,N) if (RD()) build(S,i,1); else build(i,T,1);
while (M--){
a = RD(); b = RD();
build(a,b,1); build(b,a,1);
}
printf("%d",maxflow());
return 0;
}

最新文章

  1. 【leetcode】Generate Parentheses
  2. Postgresql 取随机数
  3. vuejsLearn---通过手脚架快速搭建一个vuejs项目
  4. MongoDB学习笔记五:聚合
  5. MyEclipse快捷键敏感设置
  6. I2C总线协议的简要说明
  7. swift学习记录之代理
  8. CentOS下SSH无密码登录的配置
  9. C加密解密
  10. javascript写的ajax请求
  11. echarts 支持svg格式
  12. Base-64编码介绍
  13. 阿里云手动搭建k8s搭建中遇到的问题解决(持续更新)
  14. Jexus使用的相关记录
  15. Linux 查看系统状态
  16. 2017年3月28日15:59:16 终于明白spring这套鬼东西是怎么玩的了
  17. webpack 使用别名(resolve.alias)解决scss @import相对路径导致的问题
  18. Adreno GPU Profiler工具使用总结
  19. GoF设计模式
  20. IDEA 上传更新的代码到码云上

热门文章

  1. Apache Maven(六):存储库
  2. visual studio 2015密钥
  3. Java源码解析——集合框架(二)——ArrayBlockingQueue
  4. [Cracking the Coding Interview] 4.3 List of Depths
  5. ABAP CDS ON HANA-(8)算術式
  6. 【转】已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭
  7. Android开发——Google关于Application Not Responding的建议
  8. Mysql自学笔记
  9. 添加用户-查看用户列表-禁止默认root登陆
  10. 对mysqlbinlog日志进行操作的总结包括 启用,过期自动删除