【POJ 3041】Asteroids

【POJ 3041】Asteroids

二分图最小顶点覆盖问题
题目给出n*n的图 和m个炸弹的位置 每枚炸弹可同时炸掉一行或一列 即相同x所匹配的y看为一点 算出一个顶点集使每边所连点至少在其中出现一个 这个最小的顶点集即为所求结果
二分图最大匹配=最小顶点数

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

int link[505],k,n;
bool mp[505][505];
bool vis[505];

bool can(int s)
{
    int i;
    for(i = 1; i <= n; ++i)
    {
        if(!vis[i] && mp[s][i])
        {
            vis[i] = 1;
            if(link[i] == -1 || can(link[i]))
            {
                link[i] = s;
                return 1;
            }
            vis[i] = 0;
        }
    }
    return 0;
}

int main()
{
    int i,j,cnt,x,y;
    scanf("%d %d",&n,&k);
    memset(mp,0,sizeof(mp));
    for(i = 0; i < k; ++i)
    {
        scanf("%d %d",&x,&y);
        mp[x][y] = 1;
    }
    memset(link,-1,sizeof(link));
    cnt = 0;
    for(i = 1; i <= n; ++i)
    {
        memset(vis,0,sizeof(vis));
        if(can(i)) cnt++;
    }
    printf("%d\n",cnt);
    return 0;
}

后来看了discuss 发现用邻接链优化速度会提高很多 毕竟是稀疏图。。

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>

using namespace std;

vector <int> head[505];
int link[505],k,n;
bool vis[505];

bool can(int s)
{
    int i,v;
    for(i = 0; i < head[s].size(); ++i)
    {
        v = head[s][i];
        if(!vis[v])
        {
            vis[v] = 1;
            if(link[v] == -1 || can(link[v]))
            {
                link[v] = s;
                return 1;
            }
            vis[v] = 0;
        }
    }
    return 0;
}

int main()
{
    int i,j,cnt,x,y;
    scanf("%d %d",&n,&k);
    for(i = 0; i < k; ++i)
    {
        scanf("%d %d",&x,&y);
        head[x].push_back(y);
    }
    memset(link,-1,sizeof(link));
    cnt = 0;
    for(i = 1; i <= n; ++i)
    {
        memset(vis,0,sizeof(vis));
        if(can(i)) cnt++;
    }
    printf("%d\n",cnt);
    return 0;
}

你可能感兴趣的:(二分图最小顶点覆盖)