博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1934 [Shoi2007]Vote 善意的投票 【最小割】
阅读量:4312 次
发布时间:2019-06-06

本文共 2365 字,大约阅读时间需要 7 分钟。

题目

幼儿园里有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
#include
#include
#include
#include
#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
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;}

转载于:https://www.cnblogs.com/Mychael/p/8282746.html

你可能感兴趣的文章
Git(四) - 分支管理
查看>>
PHP Curl发送数据
查看>>
HTTP协议
查看>>
HTTPS
查看>>
git add . git add -u git add -A区别
查看>>
apache下虚拟域名配置
查看>>
session和cookie区别与联系
查看>>
PHP 实现笛卡尔积
查看>>
Laravel中的$loop
查看>>
CentOS7 重置root密码
查看>>
Centos安装Python3
查看>>
PHP批量插入
查看>>
laravel连接sql server 2008
查看>>
Laravel框架学习笔记之任务调度(定时任务)
查看>>
laravel 定时任务秒级执行
查看>>
浅析 Laravel 官方文档推荐的 Nginx 配置
查看>>
Swagger在Laravel项目中的使用
查看>>
Laravel 的生命周期
查看>>
CentOS Docker 安装
查看>>
Nginx
查看>>