首页 > 代码库 > 【网络流-二分图最大匹配】poj3041Asteroids

【网络流-二分图最大匹配】poj3041Asteroids

/*
这道题将每行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;
}

---------------------------------------------------------------------

战斗,毫不退缩;奋斗,永不停歇~~~~~~~~~~