总结 · 二分图匹配

感觉二分图匹配的内容很杂还很难理解。。。需要总结一下啊。。。。。

1.二分图最大匹配:边数最多的匹配叫做最大匹配。

算法:匈牙利算法O(V*E)

例题:BZOJ 1059 题解在这

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<queue>
 7 #include<cstring>
 8 #define PAU putchar(‘ ‘)
 9 #define ENT putchar(‘\n‘)
10 #define MSE(a,b) memset(a,b,sizeof(a))
11 #define REN(x) for(ted*e=fch[x];e;e=e->nxt)
12 #define REP(i,s,t) for(int i=s,__=t;i<=__;i++)
13 #define DWN(i,s,t) for(int i=s,__=t;i>=__;i--)
14 using namespace std;
15 const int maxn=200+10,maxm=40000+10;
16 int lnk[maxn];bool vis[maxn];
17 struct ted{int x,y;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj;
18 void add(int x,int y){*ms=(ted){x,y,fch[x]};fch[x]=ms++;return;}int n;
19 bool match(int x){
20     REN(x){int v=e->y;if(!vis[v]){vis[v]=true;
21             if(!lnk[v]||match(lnk[v])){lnk[v]=x;return true;}
22         }
23     }return false;
24 }
25 bool hungary(){
26     MSE(lnk,false);REP(i,1,n){MSE(vis,false);if(!match(i))return false;}return true;
27 }
28 inline int read(){
29     int x=0;bool sig=true;char ch=getchar();
30     for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)sig=false;
31     for(;isdigit(ch);ch=getchar())x=10*x+ch-‘0‘;return sig?x:-x;
32 }
33 inline void write(int x){
34     if(x==0){putchar(‘0‘);return;}if(x<0)putchar(‘-‘),x=-x;
35     int len=0;static int buf[20];while(x)buf[len++]=x%10,x/=10;
36     for(int i=len-1;i>=0;i--)putchar(buf[i]+‘0‘);return;
37 }
38 int T;
39 int main(){
40     T=read();while(T--){
41         MSE(fch,NULL);ms=adj;
42         n=read();
43         REP(i,1,n)REP(j,1,n)if(read())add(i,j);
44         puts(hungary()?"Yes":"No");
45     }
46     return 0;
47 }

匈牙利算法

2.二分图最小点覆盖:一个最小的点集V使得所有的边总有一个端点属于V,比如菊花图的最小点覆盖数是1

算法:最小点覆盖=最大匹配

例题:HDU 1150 题解在这

3.二分图最大独立集:一个最大的点集V使得每两点间都不存在边,比如菊花图的最大独立集是n-1。

算法:最大独立集=n-最大匹配

时间: 2024-10-12 05:32:06

总结 · 二分图匹配的相关文章

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

BZOJ 1854 游戏(二分图匹配或并查集)

此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个题需要常数优化,不能每次都fillchar一遍used数组.可以用队列将使用的used点加入,然后需要初始化的时候弹出即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <i

HDU 3081:Marriage Match II(二分图匹配+并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也可以和男生A过家家(具有传递性).给出m个关系,代表女生a和男生b没有争吵过.给出k个关系,代表女生a与女生b是好朋友.每一轮过家家之后,女生只能选择可以选择并且没选过的男生过家家,问游戏能进行几轮. 思路:因为n<=100,因此支持O(n^3)的算法,挺容易想到是一个二分图匹配的.(出现在我的网络

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我

BZOJ 1191: [HNOI2006]超级英雄Hero(二分图匹配)

云神说他二分图匹配从来都是用网络流水过去的...我要发扬他的精神.. 这道题明显是二分图匹配.网络流的话可以二分答案+最大流.虽然跑得很慢.... ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea

二分图匹配(指派问题)

指派问题: 有N台计算机和K个任务,我们可以给每台计算机分配一个任务,每台计算机能够处理的任务种类不同,请求出最多能够处理的任务的个数. 思路:二分图匹配,可以这样来定义无向二分图,G=(UuV,E); U 代表计算机的顶点集合,V代表任务的顶点集合,对于任意u属于U和v属于V,计算机u能够处理的任务v<=>(u,v)属于E 二分图例子: 对原图做如下改变: 将原图中所有无向边e改为有向边,方向从U到V,容量1,增加源点s和汇点t,从s向所有的顶点u属于U连一条容量为1的边,从所有的顶点V属于

算法模板——二分图匹配

实现功能为二分图匹配 本程序以Codevs2776为例 详见Codevs2776 1 type 2 point=^node; 3 node=record 4 g:longint; 5 next:point; 6 end; 7 var 8 i,j,k,l,m,n:longint; 9 c,f:array[0..1000] of longint; 10 a:array[0..1000] of point; 11 procedure add(x,y:longint);inline; 12 var p:

UVA 11419 - SAM I AM(二分图匹配+最小点覆盖)

UVA 11419 - SAM I AM 题目链接 题意:给定一个棋盘,上面有一些目标,现在要放炮,一个炮能打一行或一列,问最少放几个炮及放炮位置 思路:首先是二分图匹配,每个目标行列建边,做二分图匹配就是最少的放炮位置,至于输出方案,利用最小点覆盖的Konig原理去做,详细证明 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 10

二分图匹配(附算法简介)(例题: 囊地鼠)

这是一种神奇的算法. 它所解决的问题就是: 对于一个图,图上只有黑点和白点,黑点和白点之间有连边,问黑点和白点的最大匹配数是多少. 讲完问题,我们来讲讲算法. 首先我们要先找到目前没有被匹配的第一个黑色点(此算法可以只做一边(黑或白)) 然后我们找到与他连边的点,并把这两个点标记为一个匹配. 然后我们一直往下找,直到找到一个点,这个点连向的是已经被匹配过的点(记为V). 那么我们此时就尝试能否让原来与V节点匹配的点找到另一个未匹配的节点,来替代它(此时需要递归,因为有可能找到的点也是被匹配过的.