Luogu P3731 [HAOI2017]新型城市化
题目显然可以转化为求每一条边对二分图最大独立集的贡献,二分图最大独立集\(=\)点数\(-\)最大匹配数,我们就有了\(50pts\)做法。
正解的做法是在原图上跑\(Tarjan\),最开始我想复杂了,后来才意识到,只要存在这样一个强连通分量,那么断掉分量内的任意一条边都不会破坏其连通性,即不管删掉哪个连边都一定会有新的匹配补充。只要让两个点不在同一个分量里面,而且原来是满流的(匹配可行边),那么它就是一个可用边(匹配必须边)。
#include <bits/stdc++.h>
using namespace std;
const int N = 400010;
const int M = 800010;
const int INF = 0x3f3f3f3f;
struct Graph {
int cnt, head[N];
struct edge {int nxt, to, f;}e[M];
Graph () {
cnt = -1;
memset (head, -1, sizeof (head));
}
void add_edge (int u, int v, int f) {
e[++cnt] = (edge) {head[u], v, f}; head[u] = cnt;
}
void add_len (int u, int v, int f) {
add_edge (u, v, f);
add_edge (v, u, 0);
}
queue <int> q;
int cur[N], deep[N];
bool bfs (int s, int t) {
memcpy (cur, head, sizeof (head));
memset (deep, 0x3f, sizeof (deep));
deep[s] = 0; 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].to;
if (deep[v] == INF && e[i].f) {
deep[v] = deep[u] + 1;
q.push (v);
}
}
}
return deep[t] != INF;
}
int dfs (int u, int t, int lim) {
if (u == t || !lim) {
return lim;
}
int tmp = 0, flow = 0;
for (int &i = cur[u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (deep[v] == deep[u] + 1) {
tmp = dfs (v, t, min (lim, e[i].f));
lim -= tmp;
flow += tmp;
e[i ^ 0].f -= tmp;
e[i ^ 1].f += tmp;
if (!lim) break;
}
}
return flow;
}
int Dinic (int s, int t) {
int max_flow = 0;
while (bfs (s, t)) {
max_flow += dfs (s, t, INF);
}
return max_flow;
}
}G;
int n, m, _ans, id[N];
struct Query {
int u, v;
bool operator < (Query rhs) const {
return u == rhs.u ? v < rhs.v : u < rhs.u;
}
bool operator == (Query rhs) const {
return u == rhs.u && v == rhs.v;
}
}q[N], ans[N];
int A (int x) {return n * 0 + x;}
int B (int x) {return n * 1 + x;}
int read () {
int s = 0, w = 1, ch = getchar ();
while ('9' < ch || ch < '0') {
if (ch == '-') w = -1;
ch = getchar ();
}
while ('0' <= ch && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar ();
}
return s * w;
}
stack <int> sta;
int dfn[N], low[N], col[N], vis[N];
void Tarjan (int u) {
sta.push (u);
vis[u] = true;
dfn[u] = low[u] = ++dfn[0];
for (int i = G.head[u]; ~i; i = G.e[i].nxt) {
int v = G.e[i].to;
if (!G.e[i].f) continue;
if (!dfn[v]) {
Tarjan (v);
low[u] = min (low[u], low[v]);
} else if (vis[v]) {
low[u] = min (low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
int tmp; ++col[0];
do {
tmp = sta.top ();
vis[tmp] = false;
col[tmp] = col[0];
sta.pop ();
}while (tmp != u);
}
}
int main () {
cin >> n >> m;
int s = n * 2 + 1;
int t = n * 2 + 2;
for (int i = 1; i <= m; ++i) {
q[i].u = read ();
q[i].v = read ();
if (q[i].u > q[i].v) {
swap (q[i].u, q[i].v);
}
}
sort (q + 1, q + 1 + m);
for (int i = 1; i <= m; ++i) {
id[i] = G.cnt + 1;
G.add_len (A (q[i].u), B (q[i].v), 1);
G.add_len (A (q[i].v), B (q[i].u), 1);
}
for (int i = 1; i <= n; ++i) {
G.add_len (s, A (i), 1);
G.add_len (B (i), t, 1);
}
G.Dinic (s, t);
for (int i = 1; i <= t; ++i) {
if (!dfn[i]) {
Tarjan (i);
}
}
for (int i = 1; i <= m; ++i) {
if (col[A (q[i].u)] != col[B (q[i].v)] && !G.e[id[i]].f) {
ans[++_ans] = q[i];
}
}
cout << _ans << endl;
for (int i = 1; i <= _ans; ++i) {
printf ("%d %d\n", ans[i].u, ans[i].v);
}
}
Luogu P3731 [HAOI2017]新型城市化的更多相关文章
- 洛谷 P3731 [HAOI2017]新型城市化【最大流(二分图匹配)+tarjan】
我到底怎么建的图为啥要开这么大的数组啊?! 神题神题,本来以为图论出不出什么花来了. 首先要理解'团'的概念,简单来说就是无向图的一个完全子图,相关概念详见度娘. 所以关于团一般都是NP问题,只有二分 ...
- P3731 [HAOI2017]新型城市化(tarjan+网络流)
洛谷 题意: 给出两个最大团的补图,现在要求增加一条边,使得最大最大团个数增加至少\(1\). 思路: 我们求出团的补图,问题可以转换为:对于一个二分图,选择删掉一条边,能够增大其最大独立集的点集数. ...
- 【Luogu3731】[HAOI2017]新型城市化(网络流,Tarjan)
[Luogu3731][HAOI2017]新型城市化(网络流,Tarjan) 题面 洛谷 给定一张反图,保证原图能分成不超过两个团,问有多少种加上一条边的方法,使得最大团的个数至少加上\(1\). 题 ...
- 求去掉一条边使最小割变小 HAOI2017 新型城市化
先求最小割,然后对残量网络跑Tarjan.对于所有满流的边,若其两端点不在同一个SCC中,则这条边是满足条件的. 证明见 来源:HAOI2017 新型城市化
- HAOI2017 新型城市化 二分图的最大独立集+最大流+强连通缩点
题目链接(洛谷):https://www.luogu.org/problemnew/show/P3731 题意概述:给出一张二分图,询问删掉哪些边之后可以使这张二分图的最大独立集变大.N<=10 ...
- LOJ2276 [HAOI2017] 新型城市化 【二分图匹配】【tarjan】
题目分析: 这题出的好! 首先问题肯定是二分图的最大独立集,如果删去某条匹配边之后独立集是否会变大. 跑出最大流之后流满的边就是匹配边. 如果一个匹配边的两个端点在一个强连通分量里,那这条边删掉之后我 ...
- [HAOI2017] 新型城市化
给出的图中恰包含2个团,则图的补图为一个二分图,其最大独立集为原图的最大团. 我们知道,二分图的最大独立集=V-最小顶点覆盖,最小顶点覆盖=最大匹配. 问题转化为:计算删去后最大匹配减小的边集. 所以 ...
- Luogu3731 HAOI2017新型城市化(二分图匹配+强连通分量)
将未建立贸易关系看成连一条边,那么这显然是个二分图.最大城市群即最大独立集,也即n-最大匹配.现在要求的就是删哪些边会使最大匹配减少,也即求哪些边一定在最大匹配中. 首先范围有点大,当然是跑个dini ...
- 【题解】新型城市化 HAOI2017 网络流 二分图最大匹配 强连通分量
Prelude 好,HAOI2017终于会做一道题了! 传送到洛谷:→_→ 传送到LOJ:←_← 本篇博客链接:(●'◡'●) Solution 首先要读懂题. 考场上我是这样想的QAQ. 我们把每个 ...
随机推荐
- 在本地硬盘安装WinPE系统,实现UEFI引导,摆脱U盘
之前装系统一直用U盘装PE后再装系统,这次直接想把PE系统直接装在本地某个分区中,普通的PE制作工具只能直接装在一个硬盘里没法装在某个分区,百度发现没有一篇类似的文章,只能自己想办法了.目前的PE都支 ...
- python爬虫 | 一条高效的学习路径
数据是创造和决策的原材料,高质量的数据都价值不菲.而利用爬虫,我们可以获取大量的价值数据,经分析可以发挥巨大的价值,比如: 豆瓣.知乎:爬取优质答案,筛选出各话题下热门内容,探索用户的舆论导向. 淘宝 ...
- 拉勾网爬取全国python职位并数据分析薪资,工作经验,学历等信息
首先前往拉勾网“爬虫”职位相关页面 确定网页的加载方式是JavaScript加载 通过谷歌浏览器开发者工具分析和寻找网页的真实请求,确定真实数据在position.Ajax开头的链接里,请求方式是PO ...
- Saltstack_使用指南04_数据系统-Grains
1. 主机规划 Grains文档 https://docs.saltstack.com/en/latest/topics/grains/index.html 注意事项 修改了master或者minio ...
- Java11新特性!
Java11又出新版本了,我还在Java8上停着.不过这也挡不住我对他的热爱,忍不住查看了一下他的新性能,由于自己知识有限,只总结了以下八个特性: 1.本地变量类型推断 什么是局部变量类型推断? va ...
- 【Python 18】BMR计算器2.0(数值类型转换与while循环)
1.案例描述 基础代谢率(BMR):我们安静状态下(通常为静卧状态)消耗的最低热量,人的其他活动都建立在这个基础上. 计算公式: BMR(男) = (13.7*体重kg)+(5.0*身高cm)-(6. ...
- HBase Client JAVA API
旧 的 HBase 接口逻辑与传统 JDBC 方式很不相同,新的接口与传统 JDBC 的逻辑更加相像,具有更加清晰的 Connection 管理方式. 同时,在旧的接口中,客户端何时将 Put 写到服 ...
- spark推测执行的坑
1.spark推测执行开启 设置 spark.speculation=true即可 2.spark开启推测执行的好处 推测执行是指对于一个Stage里面运行慢的Task,会在其他节点的Executor ...
- Java多线程——中断机制
前言:在Java多线程中,中断一直围绕着我们,当我们阅读各种关于Java多线程的资料.书籍时,“中断”一词总是会出现,笔者对其的理解也是朦朦胧胧,因此非常有必要搞清楚Java多线程的中断机制. 1.J ...
- 好程序员web前端分享18个用CSS制作出来的东西
好程序员web前端分享18个用CSS制作出来的东西,与流行的看法相反,CSS不仅仅是用来提供一个WEB页面的基本风格,以使它看起来更有吸引力.还有很多其他的事情,CSS也可以做的很好.由于它创建动画和 ...