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 【过家家】的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. Python序列之字符串 (str)

    作者博文地址:http://www.cnblogs.com/spiritman/ Python字符串的常用操作包括以下但不限于以下操作: 字符串的替换.删除.切片.复制.连接.比较.查找.分割等 以下 ...

  2. 冲刺ing-2

    第二次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 分配任务 蔺皓雯 编写博客,查阅资料 蔡晨旸 查阅资料 曾茜 暂无 鲁婧楠 暂无 杨池宇 暂无 成员遇到的问题 队员 问题 吴伟华 暂无 ...

  3. mysql You can't specify target table 'xxx' for update in FROM clause

    含义:您不能在子句中为更新指定目标表'xxx'. 错误描述:删除语句中直接含select,如下: DELETE FROM meriadianannotation WHERE SeriesID IN ( ...

  4. java锁有哪些类(转)

    转载来源:http://www.cnblogs.com/lxmyhappy/p/7380073.html 1.Java都有哪些锁? 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/ ...

  5. 简易四则运算生成程序——添加GUI支持

    项目成员:张金生     张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...

  6. 一个form表单,多个提交按钮

    技巧就是把提交的input的类型改成button!这样就可以实现多个按钮提交! 以下是案例: <form action="" id="tijiao"> ...

  7. linux下面Zookeeper的单机模式(standalone)

    1.下载 zk下载地址 http://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/ 我用的是http://mirrors.tuna.tsinghua.e ...

  8. Vue.js checkbox 练习

    <div id="app"> <input type=" />足球 <input type=" />篮球 <input ...

  9. Contest 4

    A:cf原题.当然是不是也没什么关系. #include<iostream> #include<cstdio> #include<cstdlib> #include ...

  10. 【刷题】洛谷 P4716 【模板】最小树形图

    题目背景 这是一道模板题. 题目描述 给定包含 \(n\) 个结点, \(m\) 条有向边的一个图.试求一棵以结点 \(r\) 为根的最小树形图,并输出最小树形图每条边的权值之和,如果没有以 \(r\ ...