/* 这道题将每行x看成是结点x,没列y看成是结点y,而障碍物的坐标xy看成是从x到y的 一条边。建图后问题就变成了,找最少的点,使得这些点与所有的边相邻,即最小 点覆盖,用匈牙利算法解决。 ------------------------------- 定理:最小点覆盖数 = 最大匹配数,即求图的最大匹配即可,匈牙利算法 ------------------------------- 模板讲解: bool find(int v) { for(int i=1; i<=n; i++) { if(g[v][i] && !vis[i])如果结点i和v相邻并且未被查找过 { vis[i] = true;标记结点i为已查找过 if(link[i] == 0 || find(link[i]))link[i] == 0表示i不再前一个匹配M中||i在匹配M中,但是从与i相邻的节点出发可以有增广路 { link[i] = v;记录查找成功记录 return true;返回查找成功 } } } return false; } ------------------------------- 匈牙利算法介绍: 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名。匈牙利算法是基于 Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找 增广路径,它是一种用增广路径求二分图最大匹配的算法。 --------------------------------- */ #include <iostream> #include <cstdio> #include <cstring> #define INF 0x3f3f3f3f using namespace std; int n,k,r,c; int g[550][550]; bool vis[10010]; int link[10010]; bool find(int v) { for(int i=1; i<=n; i++) { if(g[v][i] && !vis[i]) { vis[i] = true; if(link[i] == 0 || find(link[i])) { link[i] = v; return true; } } } return false; } int main() { //freopen("input.txt","r",stdin); int ans; while(scanf("%d%d",&n,&k) != EOF) { memset(g,0,sizeof(g)); memset(link,0,sizeof(link)); for(int i = 0; i < k; i++) { scanf("%d%d",&r,&c); g[r][c] = 1; } ans = 0; for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis));//清空上次搜索时的标记 if(find(i))//从节点i尝试扩展 ans++; } printf("%d\n",ans); } return 0; }
---------------------------------------------------------------------
战斗,毫不退缩;奋斗,永不停歇~~~~~~~~~~
【网络流-二分图最大匹配】poj3041Asteroids,布布扣,bubuko.com
原文地址:http://blog.csdn.net/u013147615/article/details/38374057