匈牙利算法
题目描述:你的飞船有个强大的武器可以打小行星,一次可以攻击一行或者一列,求最少的攻击次数。
题目分析:问题可以转化为,选取最少的点,使得这些点与所有的边相邻。把方阵看做一个二分图,v1作为行顶点集,v2作为列顶点集,那x,y可以看做点,图中的点graph[x][y]则可以看做一条边,问题就是最小点覆盖数问题=最大匹配数,用匈牙利算法。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=500+10;
int v1,v2;
int graph[maxn][maxn];//构建的图
int visit[maxn];//v2的点是否访问过
int girl[maxn];//v1所匹配的y;
bool dfs(int x)
{
for(int i=1;i<=v2;i++)
{
if(graph[x][i]&&!visit[i])
{
visit[i]=1;
if(girl[i]==0||dfs(girl[i]))
{
girl[i]=x;
return true;
}
}
}
return false;
}
void solve()
{
memset(girl,0,sizeof(girl));
int cnt=0;
for(int i=1;i<=v1;i++)
{
memset(visit,0,sizeof(visit));//清空上次搜索的标记
if(dfs(i))
cnt++;
}
cout << cnt << endl;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
v1=v2=n;
memset(graph,0,sizeof(graph));
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
graph[x][y]=1;
}
solve();
return 0;
}
初学匈牙利算法,大体明白怎么回事了,以后追加新的理解。