CH#17C 舞动的夜晚(最大流+强连通分量)
舞动的夜晚 CH Round #17
描述
L公司和H公司举办了一次联谊晚会。晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞。在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一共有T对。舞会上,每位员工会尝试选择一名Ta认识的对方公司的员工作为舞伴,并且每位员工至多跳一支舞。完成的交际舞的数量越多,晚会的气氛就越热烈。顾及到晚会的气氛,员工们希望知道,哪些员工之间如果进行了交际舞,就会使整场晚会能够完成的交际舞的最大数量减小。
输入格式
第一行三个整数N、M、T。
接下来T行每行两个整数x、y,表示L公司的员工x和H公司的员工y互相认识。
输出格式
第一行一个整数cnt,表示进行了交际舞后会使整场晚会能够完成的交际舞的最大数量减小的员工有多少对。
第二行cnt个整数,升序输出这样的一hunyinhunyin对员工的认识关系的编号(他们的认识关系是在输入数据中读入的第几条认识关系)。如果cnt=0,输出一个空行。
样例输入
3 3 6
1 1
2 1
2 2
3 1
3 2
3 3
样例输出
3
2 4 5
数据范围与约定
- 对于50%的数据,1<=N,M<=100,1<=T<=1000。
- 对于100%的数据,1<=N,M<=10000,1<=T<=100000,1<=x<=N,1<=y<=M。
题解
二分图的不可行边——最大流+Tarjan
对于50%的数据,先求出最大匹配的值,然后枚举每一条边,连上之后重求最大匹配,看答案是否为原最大匹配-1。求最大匹配用匈牙利算法。
对于100%的数据,先用Dinic求任意一组最大匹配,然后建一张新图:
匹配边(i,j) j到i连边
非匹配边 (i,j) i到j连边
匹配的左点i (i,S)
不匹配的左点i (S,i)
匹配的右点j (T,j)
不匹配的右点j (j,T)然后用Tarjan求强连通分量
(i,j)是可行边的条件:
(i,j)是匹配边 或者 i,j在同一个scc里那么总边数减去可行边数就是不可行边数,即答案。
注意这个新图要包含源和汇,不能只在二分图两部之间连边,除非原最大匹配是一个完备匹配。
证明过程,写在书上了,很详细。
时间复杂度\(O(E\sqrt{N+M})\)
注意那个源汇点连边的时候,因为初始tot=1,所以枚举的是正边。
求出二分图最大匹配的不可行边板子题,使用
dinic
求最大流,tarjan
求强连通分量。
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3fffffff, u = 40010, w = 300010;
int head[u], ver[w], edge[w], Next[w], d[u], e[w], c[u], sta[u], ins[u], dfn[u], low[u];
int n, m, p, s, t, i, j, tot, maxflow, ans, x, y, scc, st, num;
char str[10];
vector<int> a[u];
queue<int> q;
void add(int x, int y, int z) {
ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
ver[++tot] = x, edge[tot] = 0, Next[tot] = head[y], head[y] = tot;
}
bool bfs() {
memset(d, 0, sizeof(d));
while (q.size()) q.pop();
q.push(s); d[s] = 1;
while (q.size()) {
int x = q.front(); q.pop();
for (int i = head[x]; i; i = Next[i])
if (edge[i] && !d[ver[i]]) {
q.push(ver[i]);
d[ver[i]] = d[x] + 1;
if (ver[i] == t) return 1;
}
}
return 0;
}
int dinic(int x, int flow) {
if (x == t) return flow;
int rest = flow, k;
for (int i = head[x]; i && rest; i = Next[i])
if (edge[i] && d[ver[i]] == d[x] + 1) {
k = dinic(ver[i], min(rest, edge[i]));
if (!k) d[ver[i]] = 0;
edge[i] -= k;
edge[i ^ 1] += k;
rest -= k;
}
return flow - rest;
}
void add2(int x, int y)
{
a[x].push_back(y);
}
void tarjan(int x)
{
dfn[x] = ++num; low[x] = num;
sta[++st] = x; ins[x] = 1;
int y;
for (int i = 0; i<a[x].size(); i++)
if (!dfn[y = a[x][i]])
{
tarjan(y);
low[x] = min(low[x], low[y]);
}
else if (ins[y]) low[x] = min(low[x], dfn[y]);
if (dfn[x] == low[x])
{
scc++;
do { y = sta[st]; st--; ins[y] = 0; c[y] = scc; } while (x != y);
}
}
int main()
{
while (cin >> n >> m >> p)
{
memset(head, 0, sizeof(head));
s = 0, t = n + m + 1; tot = 1; maxflow = 0;
for (i = 1; i <= n; i++) add(s, i, 1);
for (i = 1; i <= m; i++) add(i + n, t, 1);
for (i = 1; i <= p; i++)
{
scanf("%d%d", &x, &y);
add(x, n + y, 1), e[i] = tot;
}
while (bfs())
while (i = dinic(s, inf)) maxflow += i;
for (i = s; i <= t; i++) a[i].clear();
for (i = 1; i <= p; i++)
if (!edge[e[i]]) add2(ver[e[i]], ver[e[i] ^ 1]);
else add2(ver[e[i] ^ 1], ver[e[i]]);
for (i = 1; i <= n; i++)
if (!edge[2 * i]) add2(i, s); else add2(s, i);
for (i = 1; i <= m; i++)
if (!edge[2 * (n + i)]) add2(t, n + i); else add2(n + i, t);
memset(dfn, 0, sizeof(dfn));
memset(ins, 0, sizeof(ins));
memset(c, 0, sizeof(c));
st = num = scc = ans = 0;
for (i = s; i <= t; i++)
if (!dfn[i]) tarjan(i);
for (i = 1; i <= p; i++)
if (edge[e[i]] || c[ver[e[i]]] == c[ver[e[i] ^ 1]]) ans++;
cout << (ans = p - ans) << endl;
if (!ans) cout << endl;
for (i = 1; i <= p; i++)
if (!edge[e[i]] && c[ver[e[i]]] != c[ver[e[i] ^ 1]])
if (--ans) printf("%d ", i); else printf("%d\n", i);
}
return 0;
}
CH#17C 舞动的夜晚(最大流+强连通分量)的更多相关文章
- CH#17C 舞动的夜晚
原题链接 即求二分图的不可行边数量,因为不保证是完备匹配,所以需要通过网络流求出任意一组最大匹配,并建立新图判断. 建新图:对于跑完网络流的图上已经匹配的边,建立反边:对于没有匹配的边,建立正边(图只 ...
- [Contest Hunter#17-C] 舞动的夜晚
[题目链接] http://contest-hunter.org:83/contest/CH%20Round%20%2317/%E8%88%9E%E5%8A%A8%E7%9A%84%E5%A4%9C% ...
- ContestHunter#17-C 舞动的夜晚
Description: L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一 ...
- CH Round #17 舞动的夜晚
舞动的夜晚 CH Round #17 描述 L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的 ...
- HAOI2017 新型城市化 二分图的最大独立集+最大流+强连通缩点
题目链接(洛谷):https://www.luogu.org/problemnew/show/P3731 题意概述:给出一张二分图,询问删掉哪些边之后可以使这张二分图的最大独立集变大.N<=10 ...
- AcWing 380. 舞动的夜晚
大型补档计划 题目链接 这题是求必须边,而不是不可行边,因为不可行边 = 必须边 + 死掉了的边(貌似lyd第三版书上还是说的不可行边)先跑最大流. 在跑完以后的残余网络上,对于一条当前匹配的边 \( ...
- Poj 1904 King's Quest 强连通分量
题目链接: http://poj.org/problem?id=1904 题意: 有n个王子和n个公主,王子只能娶自己心仪的公主(一个王子可能会有多个心仪的公主),现已给出一个完美匹配,问每个王子都可 ...
- hdu 4685 二分匹配+强连通分量
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...
- BZOJ 1179 [Apio2009]Atm(强连通分量)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1179 [题目大意] 给出一张有向带环点权图,给出一些终点,在路径中同一个点的点权只能累 ...
- Kosaraju算法解析: 求解图的强连通分量
Kosaraju算法解析: 求解图的强连通分量 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 定义 连通分量:在无向图中,即为连 ...
随机推荐
- Echarts 饼图,legend样式美化
最后样式图: 实现代码: var myChart = echarts.init(document.getElementById('container')); let option = { /*{b}: ...
- Kotlin协程系列(一)
一.协程的定义 最近看了一本有关kotlin协程的书籍,对协程又有了不一样的了解,所以准备写一个关于kotlin协程系列的文章. 言归正传,我们在学习一个新东西的时候,如果连这个东西"是什么 ...
- macOS上有哪些值得推荐的常用软件
macOS 作为一款流行的操作系统,拥有丰富的第三方软件生态系统,涵盖了各种领域的应用程序.以下将介绍一些在 macOS 上备受推崇的常用软件,并对它们进行详细的介绍和说明. 1. 生产力工具 a. ...
- 湖南省网络攻防邀请赛 RE 题解
ez_apkk 解题过程: 将apk拖入jadx,查看MainActivity,发现是简单RC4加密,密钥是"55667788",最后再将加密结果+1 public String ...
- JavaWeb开发-HTML基础学习
1.HTML的基本语法 HTML是什么?:HTML是一种超文本标记语言,负责网页的结构,设计页面的元素内容等 超文本:超越文本限制,除了文本信息,还可以定义图片,音频,视频等 标记语言:由标签构成的语 ...
- WinForm窗体间传值的方法
窗体间传递数据,无论是父窗体操作子窗体,还是子窗体操作符窗体,有以下几种方式: 1.公共静态变量:2.使用共有属性:3.使用委托与事件:4.通过构造函数把主窗体传递到从窗体中: 一.通过静态变量特点: ...
- MacOS Monterey 配置 PHP 环境记录
目前 中文网中对于 MacOS 下安装 PHP 教程比较老,并且我个人感觉很难看懂.我在安装 PHP 过程中遇到了很多网络中没有出现过的问题,特此环境配置过程记录如下. 电脑:MacBook Pro ...
- idea常用快捷键使用
idea常用快捷键使用:1.shift+u 大小写2.alt+shift+u 驼峰命名(插件:CamelCase)3.ctrl+alt 点击跳转实现类4.ctrl 点击跳转接口类5.Alt+F7 查看 ...
- [ABC238G] Cubic?
Problem Statement Given a sequence $A$ of $N$ numbers, answer the following $Q$ questions. In the $i ...
- 生产升级JDK 17 必读手册
原文点这里,查看更多优质文章 DK 17 在 2021 年 9 月 14 号正式发布了!根据发布的规划,这次发布的 JDK 17 是一个长期维护的版本(LTS). Java 17 提供了数千个性能.稳 ...