BZOJ 3546 [ONTAK2010]Life of the Party (二分图最大匹配必须点)
题解:给出一个二分图,问你取点哪个点会使得二分图匹配数减少。
解法:其实就是问二分图匹配的必须点。先对初始二分图做一次最大匹配。
现在考虑左边点,看残余网络上的边重新构图:如果是匹配边那么就从右往左连边,如果是非匹配边就从左往右连边。然后从每个非匹配点出发dfs标记每一个访问过的点。最后是匹配点且未被访问过的就是必须点。为什么呢?仔细考虑新构的图,从未匹配点出发的其实也是一条增广路,如果这条增广路能访问到 已匹配点 。那么我们就可以把这条增广路取反得到另一种匹配方案,也就是说这个被访问到的 已匹配点是非必须的。
右边点原理相似。
细节详见代码以及注释:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=+;
const int M=+;
const int INF=0x3f3f3f3f;
int n1,n2,m,s,t,id[M<<];
struct edge{
int nxt,to,cap;
}edges[M<<];
int cnt=,x[M],y[M],head[N],cur[N]; int add_edge(int x,int y,int z) {
edges[++cnt].nxt=head[x]; edges[cnt].to=y; edges[cnt].cap=z; head[x]=cnt;
return cnt;
} int dep[N];
queue<int> q;
bool bfs() {
while (!q.empty()) q.pop();
memset(dep,,sizeof(dep));
dep[s]=; q.push(s);
while (!q.empty()) {
int x=q.front(); q.pop();
for (int i=head[x];i;i=edges[i].nxt) {
edge e=edges[i];
if (!dep[e.to] && e.cap) {
dep[e.to]=dep[x]+;
q.push(e.to);
}
}
}
return dep[t];
} int dfs(int x,int lim) {
if (x==t) return lim;
for (int& i=cur[x];i;i=edges[i].nxt) {
edge e=edges[i];
if (dep[x]+==dep[e.to] && e.cap) {
int flow=dfs(e.to,min(lim,e.cap));
if (flow>) {
edges[i].cap-=flow;
edges[i^].cap=+flow;
return flow; //找到一条增广路就要return
}
}
}
return ;
} int Dinic() {
int maxflow=;
while (bfs()) {
for (int i=s;i<=t;i++) cur[i]=head[i]; //当前弧优化
while (int flow=dfs(s,INF)) maxflow+=flow;
}
return maxflow;
} bool vis[N],match[N]; vector<int> G[N];
bool dfs2(int x) {
vis[x]=;
for (int i=;i<G[x].size();i++) {
int y=G[x][i];
if (!vis[y]) dfs2(y);
}
} int main()
{
scanf("%d%d%d",&n1,&n2,&m);
s=; t=n1+n2+;
for (int i=;i<=m;i++) {
scanf("%d%d",&x[i],&y[i]);
id[i]=add_edge(x[i],y[i]+n1,);
add_edge(y[i]+n1,x[i],);
}
for (int i=;i<=n1;i++) add_edge(s,i,),add_edge(i,s,);
for (int i=;i<=n2;i++) add_edge(n1+i,t,),add_edge(t,n1+i,); Dinic(); //重新构图
for (int i=;i<=n1+n2;i++) vis[i]=,match[i]=,G[i].clear();
for (int i=;i<=m;i++)
if (edges[id[i]].cap) G[x[i]].push_back(n1+y[i]); //不匹配边左到右连边
else G[n1+y[i]].push_back(x[i]),match[x[i]]=; //匹配边右到左连边
for (int i=;i<=n1;i++) if (!match[i]) dfs2(i); //从每个未匹配点出发dfs
for (int i=;i<=n1;i++)
if (match[i] && !vis[i]) printf("%d\n",i); //是匹配点且未被 未匹配点 访问的 for (int i=;i<=n1+n2;i++) vis[i]=,match[i]=,G[i].clear();
for (int i=;i<=m;i++)
if (edges[id[i]].cap) G[n1+y[i]].push_back(x[i]); //不匹配边右到左连边
else G[x[i]].push_back(n1+y[i]),match[n1+y[i]]=; //匹配边左到右连边
for (int i=;i<=n2;i++) if (!match[n1+i]) dfs2(n1+i); //从每个未匹配点出发dfs
for (int i=;i<=n2;i++)
if (match[n1+i] && !vis[n1+i]) printf("%d\n",i); //是匹配点且未被 未匹配点 访问的
return ;
}
BZOJ 3546 [ONTAK2010]Life of the Party (二分图最大匹配必须点)的更多相关文章
- BZOJ.3546.[ONTAK2010]Life of the Party(二分图匹配 ISAP)
题目链接 题意:求哪些点一定在最大匹配中. 这儿写过,再写一遍吧. 求哪些点不一定在最大匹配中.首先求一遍最大匹配,未匹配点当然不一定在最大匹配中. 设一个未匹配点为A,如果存在边A-B,且存在匹配边 ...
- bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 写法1: 二分图最大匹配 思路: 将武器的属性对武器编号建边,因为只有10000种 ...
- BZOJ 3546 Life of the Party (二分图匹配-最大流)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3546 题意:给定一个二分图.(AB两个集合的点为n,m),边有K个.问去掉哪些点后 ...
- 【刷题】BZOJ 3546 [ONTAK2010]Life of the Party
Description 一个舞会有N个男孩(编号为1..N)和M个女孩(编号为1..M),一对男女能够组成一对跳舞当且仅当他们两个人互相认识. 我们把一种人定义成这个舞会的life:当且仅当如果他(她 ...
- [bzoj 1059][ZJOI 2007]矩阵游戏(二分图最大匹配)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1059 分析:不论如何交换,同一行或同一列的点还是同一行或同一列,如果我们称最后可以排成题目要求 ...
- BZOJ 4443: [Scoi2015]小凸玩矩阵 二分图最大匹配+二分
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4443 题解: 二分答案,判断最大匹配是否>=n-k+1: #include< ...
- BZOJ 3993: [SDOI2015]星际战争 [二分答案 二分图]
3993: [SDOI2015]星际战争 题意:略 R1D2T1考了裸二分答案+二分图最大匹配... #include <iostream> #include <cstdio> ...
- [bzoj 1143]最长反链二分图最大匹配
Dilworth定理:偏序集能划分成的最少的全序集的个数与最大反链的元素个数相等. 证明:http://www.cnblogs.com/itlqs/p/6636222.html 题目让求的是最大反链的 ...
- POJ 2226二分图最大匹配
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
随机推荐
- java 高性能Server —— Reactor模型单线程版
NIO模型 NIO模型示例如下: Acceptor注册Selector,监听accept事件 当客户端连接后,触发accept事件 服务器构建对应的Channel,并在其上注册Selector,监听读 ...
- JQuery 获取表格table所有行第一列
main_table 是表ID $("#main_table tr").find("td:eq(0)")
- 调用opencv的接口实现人脸检测(简单)
import cv2 import matplotlib.pyplot as plt %matplotlib inline # 提取预训练的人脸检测模型,提前下载好的模型 face_cascade = ...
- css雪碧图实现数字切换
vue中 css 雪碧图应用及数字切换demo 1. CSS Sprites一般只能使用到固定大小的盒子(box)里,这样才能够遮挡住不应该看到的部分. 2.使用css雪碧图的优点: 利用CSS Sp ...
- docker 运行jenkins及vue项目与springboot项目(一.安装docker)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- js 中数组传递到后台controller 批量删除
/*批量删除*/function datadel(url) { var ids=[]; $("input[type='checkbox']:checked").each(funct ...
- 【多线程】synchronized 和ReentrantLock
1. 锁的实现 synchronized 是 JVM 实现的,而 ReentrantLock 是 JDK 实现的. 2. 性能 新版本 Java 对 synchronized 进行了很多优化,例如自旋 ...
- shell(计算机壳层)(一)
在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的command和后来的cmd.exe.它接收用户命令,然后调用相应的应用程序. wi ...
- [CSP-S模拟测试]:影子(并查集+LCA)
题目描述 一个人有很多的影子,新的旧的,他们不断消失重来.学者的影子在他苍白色的精神图景里成为了$n$个黑色的点,他们伸长的触手交叉形成了一颗黑色的树.假使每个影子点拥有一个权值$d_i$,黑色的树边 ...
- python 国内镜像加速
原因 经常在使用Python的时候需要安装各种模块,而pip是很强大的模块安装工具但是由于国外官方默认pip访问速度慢,经常被墙,导致无法安装,所以我们最好是将自己使用的pip源更换一下,这样就能解决 ...