10566 Bimatching

  • 题意:一个男生必须跟两个女生匹配,求最大匹配

  • 思路:一般的二分图匹配做不了,网络流也不会建图,这题采用的是一般图匹配

  • 首先在原来二分图的基础上,将一个男生拆成两个点

  • 两个点之间有一条边,这样图至少会有n个匹配

  • 如果想要答案加1,只有当这两个点跟两个女生匹配的时候

  • 所以最后的答案是一般图最大匹配减去n

  • 一般图最大匹配用带花树

#pragma GCC optimize(3, "Ofast", "inline")

#include<bits/stdc++.h>

using namespace std;
const int maxn = 305;
const int maxm = 50050; struct bloosom {
struct edge {
int to, next;
} e[maxm];
int tot = 0, head[maxn]; inline void add(int u, int v) {
++tot;
e[tot].to = v, e[tot].next = head[u], head[u] = tot;
++tot;
e[tot].to = u, e[tot].next = head[v], head[v] = tot;
} int fa[maxn], tag = 0, pre[maxn], match[maxn], q[maxn], r, fl[maxn];
int vis[maxn], all; int findx(int x) {
if (fa[x] == x)return x;
return fa[x] = findx(fa[x]);
} int lca(int u, int v) {
++tag;
u = findx(u);
v = findx(v);
for (;; swap(u, v)) {
if (u) {
if (fl[u] == tag)return u;
fl[u] = tag;
u = findx(pre[match[u]]);
}
}
} void blo(int u, int v, int l) {
for (; findx(u) != l; v = match[u], u = pre[v]) {
pre[u] = v;
if (vis[match[u]] == 1)vis[q[++r] = match[u]] = 0;
if (findx(u) == u) fa[u] = l;
if (findx(match[u]) == match[u]) fa[match[u]] = l;
}
} bool aug(int s) {
for (int j = 1; j <= all; ++j) {
fa[j] = j;
vis[j] = -1;
}
vis[q[r = 1] = s] = 0;
int x, y;
for (int i = 1; i <= r; ++i) {
for (int j = head[x = q[i]]; j; j = e[j].next) {
if (vis[y = e[j].to] == -1) {
pre[y] = x;
vis[y] = 1;
if (!match[y]) {
for (int u = x, v = y, t; u; v = t, u = pre[v]) {
t = match[u];
match[u] = v;
match[v] = u;
}
return 1;
}
vis[q[++r] = match[y]] = 0;
} else if (!vis[y] && findx(x) != findx(y)) {
int l = lca(x, y);
blo(x, y, l);
blo(y, x, l);
}
}
}
return 0;
} inline void init() {
for (int i = 0; i <= all; ++i) {
pre[i] = match[i] = head[i] = 0;
}
tot = 0;
} int solve() {
int ans = 0;
for (int i = 1; i <= all; ++i) {
if (!match[i]) {
if (aug(i)) ans++;
}
}
return ans;
}
} st; int main() {
int _;
scanf("%d", &_);
while (_--) {
int n, m, s;
scanf("%d%d", &n, &m);
st.all = n * 2 + m;
st.init(); for (int i = 1; i <= n; ++i) {
st.add(i, i + n);
for (int j = 1; j <= m; ++j) {
scanf("%1d", &s);
if (s) {
st.add(i, j + (n << 1));
st.add(i + n, j + (n << 1));
}
}
}
printf("%d\n", st.solve() - n);
}
return 0;
}

[一般图最大匹配]Bimatching的更多相关文章

  1. UOJ79 一般图最大匹配

    题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人 ...

  2. [转]带花树,Edmonds's matching algorithm,一般图最大匹配

    看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...

  3. HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

    一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...

  4. 【Learning】带花树——一般图最大匹配

    一般图最大匹配--带花树 问题 ​ 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. ​ 这个问题的退化版本就是二分图最大匹配. ​ 由于二分图中不存在奇环,偶环对最大匹配并无 ...

  5. HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】

    <题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...

  6. 【UOJ#79】一般图最大匹配(带花树)

    [UOJ#79]一般图最大匹配(带花树) 题面 UOJ 题解 带花树模板题 关于带花树的详细内容 #include<iostream> #include<cstdio> #in ...

  7. ZOJ 3316 Game 一般图最大匹配带花树

    一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...

  8. [WC2016]挑战NPC(一般图最大匹配)

    [WC2016]挑战NPC(一般图最大匹配) Luogu 题解时间 思路十分有趣. 考虑一个筐只有不多于一个球才有1的贡献代表什么. 很明显等效于有至少两个位置没有被匹配时有1的贡献. 进而可以构造如 ...

  9. 【learning】一般图最大匹配——带花树

    问题描述 ​ 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...

随机推荐

  1. 恒生UFX交易接口基本介绍

    https://zhidao.baidu.com/question/203296047903136445.html 1.恒生UFT和UFX有什么区别? UFT是一个极速交易系统,UFX是一个统一接入系 ...

  2. 《打造扛得住的MySQL数据库架构》第4章 MySQL数据库结构优化

    4-1 数据库结构优化介绍 良好的数据库逻辑设计和物理设计是数据库获得高性能的基础. 1.减少不必要的数据冗余. 2.尽量避免数据维护中出现更新,插入和删除异常. 插入异常:如果表中的某个实体随着另一 ...

  3. sublime中设置scala编译运行

    Attention: 前提.前提.前提:电脑上安装scala和jdk,可以在cmd中运行scala命令: okay,next: 1.配置内容 在Tools->Build Systems-> ...

  4. 内存管理之栈stack

    1.什么是栈   栈是一种数据结构,C语言中使用栈来保存局部变量.栈是被发明出来管理内存的.2.栈管理内存的特点(小内存.自动化)   先进后出  FILO   first in last out   ...

  5. Python笔记_第四篇_高阶编程_二次封装

    1.二次封装: 二次封装其实就是对一个类或者一个方法进行二次的改造增加新的功能. 2.一个类的二次封装: 我们以一个进程为例,我们把Process这个库进行二次封装,增加一些功能,在调用. thoma ...

  6. Delphi调用c++写的dll (me)

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  7. Aras Innovator获取项目任务序列号

    //方法名:GetProjectTasksNumber //功能描述:获取项目任务序列号 //原作者:joe //创建时间:20141225 //版权所有(C)JOE.FAN //---------- ...

  8. 题解 LOJ-6485 【LJJ学二项式定理】

    题目 由于看到正解的单位根反演过于复杂 (也就是看不懂) 所以自己构造了一个算法,理论上这个算法应该还有成长的空间(可以变得普适性更强) 不知道和单位根反演有没有一样,就发表出来了 反正转载前记得要联 ...

  9. 探讨 Git 代码托管平台的若干问题 - 2019 版

    关于 Git 版本控制软件种类繁多,维基百科收录的最早的版本控制系统是 1972 年贝尔实验室开发的 Source Code Control System.1986 年 Concurrent Vers ...

  10. easyExcel入门

    1.easyExcel是处理excel的阿里开源的框架,类似poi.官网地址:https://github.com/alibaba/easyexcel 2.为什么用easyExcel? 1).占用内存 ...