poj3041(最小点覆盖)

  题目问的是使用武器一次可以摧毁一行或一列的陨石,最少使用多少次?这个是求最小点覆盖的问题,也就是问最少多少点可以覆盖所有的边。

    然后最小点覆盖又可以等于二分图的最大匹配,所以就建图求最大匹配 这题 建图的用的陨石的x坐标和y坐标,把陨石的x坐标集合和y坐标集合作为2个点集,然后把每一个陨石对应的x,y连接,比如一个陨石(2,7),那么2加入点集1,7加入点集2,然后连接2和7.

  最小点覆盖等于二分图的最大匹配的证明

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
vector<int>g[505];
int used[505],nxt[505];
bool visx[505];
int n,k;
bool ifind(int x)
{
    int sz=g[x].size();
    for(int i=0;i<sz;i++)
    {
        int v=g[x][i];
        if(!used[v])
        {
            used[v]=1;
            if(nxt[v]==0||ifind(nxt[v]))
            {
                nxt[v]=x;
                return true;
            }
        }
    }
    return false;
}
int match()
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(visx[i]&&ifind(i))
            ans++;
    }
    return ans;
}
int main()
{

    memset(nxt,0,sizeof(nxt));



    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        int h,l;
        cin>>h>>l;
        visx[h]=true;

        g[h].push_back(l);
    }

    //cout<<"**********"<<endl;
   // for(int i=1;i<=n;i++)
    //{


       // for(int j=1;j<=n;j++)
         //   cout<<line[i][j]<<" ";
       // cout<<endl;
   // }
    //cout<<"*****"<<endl;

    //for(int i=1;i<=5;i++)
       // if(visx[i]) cout<<i<<" ";
    //for(int i=1;i<=5;i++)
       //if(visy[i]) cout<<i<<" ";
    cout<<match()<<endl;
    return 0;

}

猜你喜欢

转载自blog.csdn.net/qq_40642465/article/details/81267636