题解 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 & ...
随机推荐
- PKI(Public Key Infrastucture)介绍
PKI(Public Key Infrastucture)介绍 根据Wikipedia PKI词条整理. PKI(Public Key Infrastucture)是一系列的规则.策略以及过程,可以用 ...
- ES6的新特性(17)——Generator 函数的异步应用
Generator 函数的异步应用 异步编程对 JavaScript 语言太重要.Javascript 语言的执行环境是“单线程”的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Gener ...
- 软件工程 speedsnail 第二次冲刺10
20150527 完成任务:蜗牛碰到线后速度方向的调整:已经基本实现多方向的反射: 遇到问题: 问题1 反射角的问题 解决1 利用tan()三角函数 明日任务: 大总结.找到新问题.布置下一次冲刺方案
- Transparent Flow Migration for NFV
Transparent Flow Migration for NFV 摘要 因为SDN提供的灵活性,NF之间存在着流量的迁入和迁出问题.而且NF也要根据相关的状态信息处理数据包,所以流量迁移必须满足以 ...
- 【数位dp】Enigma
http://codeforces.com/gym/101889 E 与一般数位dp不同,保存的是能否满足条件,而非记录方案数 代码: #include <iostream> #inclu ...
- C++ Primer Plus学习:第七章
C++入门第七章:函数-C++的编程模块 函数的基本知识 要使用C++函数,必须完成如下工作: 提供函数定义 提供函数原型 调用函数 库函数是已经定义和编译好的函数,可使用标准库头文件提供原型. 定义 ...
- Qt容器类汇总说明
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt容器类汇总说明 本文地址:http://techieliang.com/2017/ ...
- Spring配置声明
<... xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="htt ...
- 【c】线性表
数据对象集:线性表是N(>=0)个元素构成的有序序列,a1,a2,a3.....a(N-1),aN,a(N+1) 线性表上的基本操作有: ⑴ 线性表初始化:Init_List(L)初始条件:表L ...
- html5兼容
You can download the latest version of HTML5shiv from github or reference the CDN version at https:/ ...