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;
}