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定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
随机推荐
- setlocale - 设置当前的区域选项
总览 (SYNOPSIS) #include <locale.h> char *setlocale(int category, const char * locale); 描述 (DESC ...
- 配置阿里云SLB全站HTTPS集群
配置阿里云SLB全站HTTPS集群(以下内容仅为流程,信息可能有些对应不上) 1 登录阿里云购买两台实例 1.1 按量付费购买两台实例 1.2 配置网络可以不选择分配外网 1.3 自定义密码 1.4 ...
- Dev常用控件
GridControl TreeView DEV GridControl小结.. https://blog.csdn.net/happy09li/article/details/7186829 Dev ...
- poj 2104 无修改主席树
题目大意: 求序列的区间第k大 基本思路: 因为我根本就没有思路,知道这是主席树,我就去学了下,在b站上看了uestc的教学视频,然后看了一篇博客,博客http://www.cnblogs.com/E ...
- easyui记录
var rows = top.$("#queryDetailGrid").datagird("getRows"); //获取datagird所有行 top.$( ...
- [REPRINT]MySQL Indexing Explained
https://atech.blog/viaduct/mysql-indexes-primer What are Indexes? Every time your web application ru ...
- 【leetcode】207. Course Schedule
题目如下: There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have ...
- Android学习--apk打包过程
1. 使用aapt工具,给所有的res目录下的资源文件生成对应的id,id会被放进R.java文件中 2. JavaC编译器,将所有Java文件转换为Class文件,其中,内部类会分别生成.class ...
- Linux 下虚拟机——Virtual Box
下面介绍几款可以在Linux下运行的虚拟机 VMware,VirtualBox, QEMU, Xen.(其中我只用过VirtualBox 和Xen, 我是新手,其他两个没时间折腾,所以下面的资料都几乎 ...
- 分布式系统理论基础2 :CAP
本文转自:https://www.cnblogs.com/bangerlee/p/5328888.html 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到 ...