首页 > 代码库 > 二分图最大匹配

二分图最大匹配

POJ 3041

Bessie 驾驶着他的太空飞船呆呆2号在太空旅行,途径一段危险地带,他希望自己能安全通过这段区域,于是他将这片区域的地图扫描进入了太空飞船,地图是一个N x N的网络 (1 <= N <= 500),其中有K颗小行星 (1 <= K <= 10,000)。

还好Bessie有一个强力的武器能够一发光束将一整行或者一整列的小行星轰成灰烬。 这种光束的价格高昂,材料稀有,所以他希望更少的使用这个光束。现在把地图给你,你能帮Bessie计算一下,摧毁掉这些小行星至少需要几发光束。

Input
* Line 1: 两个整数N和K,中间用空格隔开。
* Lines 2..K+1: 每一行有两个整数R和C (1 <= R, C <= N) ,代表行和列,即小行星i的位置是(Ri,Ci)。
Output
* Line 1: 输出一个整数表示最少需要几发光束。
Sample Input
3 4
1 1
1 3
2 2
3 2
Sample Output
2

分析:
建图用行和列 行->列 即每个坐标对应一个边 然后找最大匹配即为所求
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 using namespace std;
 6 int mmap[555][555];//存图
 7 int vis[555];
 8 int match[555];//匹配过
 9 int n;//总点数
10 bool dfs(int u)
11 {
12     for (int v = 1; v <= n; v++)
13     {
14         if (mmap[u][v] && !vis[v])
15         {
16             vis[v] = true;
17             if (match[v] == -1 || dfs(match[v]))
18             {
19                 match[v] = u;
20                 return true;
21             }
22         }
23     }
24     return false;
25 }
26 int main()
27 {
28     memset(mmap, 0, sizeof(mmap));
29     int k;//边数
30     scanf("%d%d", &n, &k);//n个点k个边
31     int i, a, b;
32     for (i = 0; i<k; i++)
33     {
34         scanf("%d%d", &a, &b);
35         mmap[a][b] = 1;//连边a->b 要单向边
36     }
37     int sum = 0;//匹配数
38     memset(match, -1, sizeof(match));//初始化为-1
39     for (int i = 1; i <= n; i++)
40     {
41         memset(vis, 0, sizeof(vis));
42         if (dfs(i))//是否有增广路,有的话匹配数+1
43             sum++;
44     }
45     printf("%d\n", sum);
46 }

 

**最小路径覆盖

定义:在一个PXP的有向无环图中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联
定理:最小路径覆盖=|总点数|-最大匹配数

POJ1422

一个地图上有n个小镇,以及连接着其中两个小镇的有向边,而且这些边无法形成回路。现在选择一些小镇空降士兵(1个小镇最多1个士兵),士兵能沿着边走到尽头,问最少空降几个士兵,能遍历完所有的小镇
 

建图后直接找最大匹配数,点数-最大匹配书即为所求


 

**最大独立集

设G=(v,e)是n阶图,如果G的顶点集合中U中任何两个顶点都不邻接,则称它为独立集。
最大独立集:在一个独立集中顶点的最大个数称为图G的独立数
设最大匹配边集是M,那么最大独立集个数|U|=|总点数|-|最大匹配数|

POJ2771

老师要带学生们出去远行,但是这个保守的老师不希望男女生们在旅行途中恋爱,所以他要使得谈恋爱的可能性尽量小,并且带出去最多的学生。


根据条件,将恋爱的人连边。
求出最大独立集。


 

二分图最大匹配