题解 P1682 【过家家】
P1682 过家家
题目描述
有2n个小学生来玩过家家游戏,其中有n个男生,编号为1到n,另外n个女生,编号也是1到n.每一个女生可以先选择一个和她不吵嘴的男生来玩,除此之外,如果编号为X的女生的朋友(也是女生,且编号为Y)不和编号为Z的男生吵嘴,那么X也可以选择Z.此外,朋友关系是可以传递的,比如a和b是朋友,b和c是朋友,那么我们可以认为a和c也是朋友.
当每一位女生都选择了玩伴,那么他们会开始新一轮游戏.在每一轮后,每个女生都会开始去找一个新的男生做玩伴(以前没选过).而且每一个女生最多能强制k个男生接受,无论他们以前是否吵嘴.
现在你的任务就是确定这2n个小学生最多能玩几轮游戏.
输入输出格式
输入格式:
第一行有4个整数n,m,k,f(3<=n<=250,0<m<n*n,0<=f<n).
n表示有2n个小学生,其中n个男生n个女生.
接下来m行,每行包含2个数字a,b表示编号为a的女生和编号为b的男生从没吵嘴过.
再接下来f行,每行包含2个数字c,d表示编号为c的女生和编号为d的女生是朋友.
输出格式:
对于每组数据,输出一个整数,表示2n个小学生最多能玩几轮.
这一题和P3153 [CQOI2009]跳舞几乎是一模一样,那篇题解可以看这里,建图 + 最大流 + 二分即可得到答案,这里不在赘述,写这篇题解是要解决题目中连通性的问题
题目中有提到过,朋友关系是可以传递的,比如a和b是朋友,b和c是朋友,那么我们可以认为a和c也是朋友,据此我们有两个思路:
1.并查集
2.Floyd
并查集是否可行
虽然我很擅长并查集,但是很可惜,并查集的做法在这题并不是特别适用:理由如下:
并查集的最大用处是,利用父亲这一概念很方便的判断两元素是否处于同一集合,但通过某一节点,我们不能很快确定其他节点是否与他在一集合内,唯一想到的方法是遍历所有节点,一一判断是否属于同一集合,比较麻烦,故不适用并查集。
Floyd是否可行
Floyd算法可以判断图的联通性,伪代码大概如下:
for(所有节点(作为中间点)){
for(所有节点(作为起点)){
for(所有节点(作为终点)){
if(起点与中间点联通 && 中间点与终点联通)
起点与终点联通
}
}
}
这就是传递闭包,能适用与这题,理由如下:
利用传递闭包,我们在处理完关系之后可以得到一个二维数组,可以很容易的判断两点是否联通
所以我们使用Floyd传递闭包,解决关系问题,不过要对上述伪代码做适当修改:(男孩B和女孩A玩 && 女孩A和女孩C是朋友)---> 男孩和女孩C玩
所以我们得到代码:
void Floyd(){
for(int k = num + 1;k <= 2 * num;k++){//所有女孩
for(int i = 1;i <= num;i++){//所有男孩
for(int j = num + 1;j <= 2 * num;j++){//所有女孩
dance[i][j] |= dance[i][k] && dance[k][j];//男孩选女孩(建图是也是先男孩再连女孩)
}
}
}
}
//主函数部分
for(int i = 1;i <= nr;i++){
u = RD();v = RD();
dance[v][u + num] = 1;//女孩编号 + num
}
for(int i = 1;i <= nf;i++){
u = RD();v = RD();
dance[u + num][v + num] = dance[v + num][u + num] = 1;
}
Floyd();
最后二分多次建图跑最大流验证答案即可
Code
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int RD(){
int out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const int maxn = 100019,INF = 1e9;
int num,k,nr,nf,nume = 1;
int dance[190][190];
int frind[190][190];
int s,t,maxflow;
int head[maxn << 2];
struct Node{
int v,dis,nxt;
}E[maxn << 3];
void add(int u,int v,int dis){
E[++nume].nxt = head[u];
E[nume].v = v;
E[nume].dis = dis;
head[u] = nume;
}
int d[maxn];
bool bfs(){
queue<int>Q;
memset(d,0,sizeof(d));
d[s] = 1;
Q.push(s);
while(!Q.empty()){
int u = Q.front();Q.pop();
for(int i = head[u];i;i = E[i].nxt){
int v = E[i].v;
if(E[i].dis && !d[v]){
d[v] = d[u] + 1;
if(v == t)return 1;
Q.push(v);
}
}
}
return 0;
}
int Dinic(int u,int flow){
if(u == t)return flow;
int rest = flow,k;
for(int i = head[u];i;i = E[i].nxt){
int v = E[i].v;
if(d[v] == d[u] + 1 && rest && E[i].dis){
k = Dinic(v,min(rest,E[i].dis));
if(!k)d[v] = 0;
E[i].dis -= k;
E[i ^ 1].dis += k;
rest -= k;
}
}
return flow - rest;
}
void build(int a){
memset(head,0,sizeof(head));
nume = 1;
for(int i = 1;i <= num;i++){
add(s,i,a);
add(i,s,0);//源点到每个♂
add(i + num,i + 2 * num,k);
add(i + 2 * num,i + num,0);//♀分两部
add(i + 2 * num,t,a);
add(t,i + 2 * num,0);//女到汇点
}
for(int i = 1;i <= num;i++){
for(int j = num + 1;j <= 2 * num;j++){
if(dance[i][j]){
add(i,j + num,1);
add(j + num,i,0);
}
else{
add(i,j,1);
add(j,i,0);
}
}
}
}
bool check(int mid){
build(mid);
maxflow = 0;
int flow = 0;
while(bfs())while(flow = Dinic(s,INF))maxflow += flow;
if(maxflow == mid * num)return 1;
return 0;
}
int search(int l,int r){
int ans;
while(l <= r){
int mid = l + r >> 1;
if(check(mid))l = mid + 1,ans = mid;
else r = mid - 1;
}
return ans;
}
void Floyd(){
for(int k = num + 1;k <= 2 * num;k++){
for(int i = 1;i <= num;i++){
for(int j = num + 1;j <= 2 * num;j++){
dance[i][j] |= dance[i][k] && dance[k][j];
}
}
}
}
int main(){
num = RD();nr = RD();k = RD();nf = RD();
s = num * 4 + 19;t = s + 1;
int u,v;
for(int i = 1;i <= nr;i++){
u = RD();v = RD();
dance[v][u + num] = 1;
}
for(int i = 1;i <= nf;i++){
u = RD();v = RD();
dance[u + num][v + num] = dance[v + num][u + num] = 1;
}
Floyd();
printf("%d\n",search(0,num + k));
return 0;
}
题解 P1682 【过家家】的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- 2.hive里的增删改查
1.hive的增删改查 查询数据库 hive> show databases; OK default Time taken: 0.254 seconds, Fetched: 1 row(s) h ...
- 2017软工第十周个人PSP
11.17--11.23本周例行报告 1.PSP(personal software process )个人软件过程. C(类别) C(内容) ST(开始时间) ET(结束时间) INT(间隔时间) ...
- UML设计(团队作业6)
决胜 Poker 一.团队成员 学号 姓名 211606392 郑俊瑜 (队长) 211606327 冉繁盛 211606323 刘世华 211606386 姚皓钰 211606358 陈卓楠 211 ...
- HDU 5501 The Highest Mark
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5501 The Highest Mark Accepts: 32 Submissions: 193 ...
- lilntcode-508-摆动排序
508-摆动排序 给你一个没有排序的数组,请将原数组就地重新排列满足如下性质 nums[0] <= nums[1] >= nums[2] <= nums[3].... 注意事项 请就 ...
- 第二章 script元素
<script>元素 async:可选.表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本.只对外部脚本文件有效. charset:可选.表示通过 ...
- IT行业大学生就业分析报告感想
现如今的高校毕业生每年都在增长,就业压力只增不减,人才市场挤满了人 学生们普遍的表现出就业难的情况,并且适合自己的工作也难找 从报告中也容易看出IT行业很吸引人,也是人数最多的,因此机会也就变少了 在 ...
- PHP Mailer 发送邮件
<?php /* 下载网址 https://github.com/PHPMailer/PHPMailer 打开下载的压缩包文件目录 将 PHPMailer-master 下的 src 文件夹复制 ...
- 可以从Jar外部加载JDBC.properties的Spring-mybatis配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- Mybatis 点点滴滴
相比 Hibernate ,Mybatis 实在是学习门槛低多了. 1 . 类属性和表字段的自动对应 当向数据库中插入一行数据时,<insert>标签中的占位符#{}中的占位符的值写 mo ...