热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

BZOJ1934[Shoi2007]善意投票问题的最小割解决方案

在幼儿园中,有\(n\)个小朋友需要通过投票来决定是否午睡。尽管这个问题对每个孩子来说并不是特别重要,但他们仍然希望通过谦让的方式达成一致。每个人都有自己的偏好,但为了集体和谐,他们决定采用一种最小割的方法来解决这一问题。这种方法不仅能够确保每个人的意愿得到尽可能多的尊重,还能找到一个最优的解决方案,使整体满意度最大化。

题目

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


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



推荐阅读
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
author-avatar
钓鱼翁玩围脖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有