您的位置:首页 > 其它

poj 3041 二分匹配基础

2013-01-23 19:39 295 查看
行列建边。
konig定理:二分图的最小顶点覆盖数等于最大匹配数。
证明:
比如最大匹配是M。为了求最少的点让每条边都至少和其中一个点关联。
M个点是足够的。就是说他们覆盖最大匹配的那M条边后,假设有某边e没被覆盖,那么把e加入后会得到一个更大的匹配,出现矛盾。
M个点是必需的。匹配的M条边,由于他们两两无公共点,就是说至少有M个点才能把他们覆盖。

题目大意:在一片由N * N(1 ≤ N ≤ 500)的方格阵表示的宇宙空间里,有些格子里面有一些小行星(Asteroid),小行星共有K(1 ≤ K ≤ 10,000)个。Bessie要在这个地区航行,它就需要消灭所有的小行星。Bessie有一种被称作“applepi破坏光线”的超级武器。正如这个威武的名字一样,发动一次就可以破坏一行或者一列里面所有的小行星。由于“applepi破坏光线”的弹药是很贵的,Bessie决定节俭地使用这种武器。你需要计算它至少需要使用多少次“applepi破坏光线”。

简单地说,题意就是在一个n*n的矩阵中,存在m颗行星,每次可清除一行或一列的行星,询问至少几次才能清除完所有行星。 首先是转换,将每行看作一点放入x点集,将每列看作一点放入y点集,对于一颗在i行j列的行星,则对x点集中i号点向y点集中j号点连一条边,然后就是求二分图的最小点覆盖了。

View Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
// Accepted    1448K    94MS    C++    918B
const int MAXN = 555;
vector<int>map[MAXN];
int pre[MAXN];
int vis[MAXN*MAXN];
int n, m;

void init()
{
memset( pre, 0, sizeof(pre) );
int i;
for( i = 0; i <= n; i++ )map[i].clear();
}

int dfs( int u )
{
int i, v, size;
size = map[u].size();
for( i = 0; i < size; i++ )
{
v = map[u][i];
if( !vis[v] )
{
vis[v] = 1;
if( !pre[v] || dfs( pre[v] ) )
{
pre[v] = u;
return 1;
}
}
}
return 0;
}

int MaxMatch()
{
int u, cnt;
cnt = 0;
for( u = 1; u <= n; u++ )
{
memset( vis, false, sizeof(vis) );
cnt += dfs( u );
}
return cnt;
}

int main()
{
int x, y, i;
scanf( "%d%d", &n, &m );
init();
for( i = 0; i < m; i++ )
{
scanf( "%d%d", &x, &y );
map[x].push_back( y );
}
printf( "%d\n", MaxMatch() );
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: