poj3041(最小顶点覆盖)
2013-05-30 11:07
148 查看
http://poj.org/problem?id=3041
Asteroids
Description
Bessie wants to
navigate her spaceship through a dangerous asteroid field in the
shape of an N x N grid (1 <= N <= 500). The grid contains K
asteroids (1 <= K <= 10,000), which are conveniently located
at the lattice points of the grid.
Fortunately, Bessie has a powerful weapon that can vaporize all the
asteroids in any given row or column of the grid with a single
shot.This weapon is quite expensive, so she wishes to use it
sparingly.Given the location of all the asteroids in the field,
find the minimum number of shots Bessie needs to fire to eliminate
all of the asteroids.
Input
* Line 1: Two
integers N and K, separated by a single space.
* Lines 2..K+1: Each line contains two space-separated integers R
and C (1 <= R, C <= N) denoting the row and column
coordinates of an asteroid, respectively.
Output
* Line 1: The
integer representing the minimum number of times Bessie must
shoot.
Sample Input
Sample Output
Hint
INPUT DETAILS:
The following diagram represents the data, where "X" is an asteroid
and "." is empty space:
X.X
.X.
.X.
OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and
(1,3), and then she may fire down column 2 to destroy the asteroids
at (2,2) and (3,2).
Source
USACO 2005 November Gold
题意:
解题思路:
把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1、V2,其中| V1|=| V2|)
然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。
再利用二分图最大匹配的König定理:
最小点覆盖数 = 最大匹配数
(PS:最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。)
因此本题自然转化为求 二分图的最大匹配 问题
求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。但是这个算法的时间复杂度为边数的指数级函数。
因此,需要寻求一种更加高效的算法——用增广路求最大匹配的方法(匈牙利算法)
增广路的定义(也称增广轨或交错轨):
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。
由增广路的定义可以推出下述三个结论:
1、P的路径个数必定为奇数,第一条边和最后一条边都不属于M。
2、将M和P进行取反操作可以得到一个更大的匹配M’
(反操作:把P中的 匹配边 与 非匹配边 互换)
3、M为G的最大匹配当且仅当不存在M的增广路径P
匈牙利算法轮廓:
(1)置M为空
(2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M
(3)重复(2)操作直到找不出增广路径为止
其实就是求最大匹配,自己在图上模拟下就知道了。。
因为对模版的理解不到位导致wa-re了无数次。。
代码1:(以前做的),建议代码2
#include
#include
using namespace std;
#define MAXN 10010
int map[502][502];
int vis[MAXN],flag[MAXN];
int n,m;
bool dfs(int a)//寻找从a出发的对应项出的可增广路
{
int i;
for(i=1;i<=n;i++)//从邻接表中列举a能关联到顶点i
{
if(map[a][i]&&!vis[i])//i不在增广路上
{
vis[i]=1;//把i加入增广路;
if(flag[i]==0||dfs(flag[i]))//i是未盖点
或者 从i的对应项出发有可增广路
{
flag[i]=a;//修改i的对应项为a;
return
true;//则从i的对应项出有可增广路,返回true
}
}
}
return false;
}
int main()
{
int i;
while(cin>>n>>m)//n图的大小n*n,m个点(行星)
{
memset(map,0,sizeof(map));
for(i=1;i<=m;i++)
{
int
x,y;
cin>>x>>y;
map[x][y]=1;
}
memset(flag,0,sizeof(flag));
int result=0;
for(i=1;i<=n;i++)//void
匈牙利hungary()
{
memset(vis,0,sizeof(vis));
if(dfs(i))//则从i的对应项出有可增广路
result++;//匹配数++;
}
cout<<result<<endl;//输出
匹配数;
}
return 0;
}
代码2:套模版
#include
#include
#include
using namespace std;
const int maxn=10010;
int uN,vN;
int xM[maxn],yM[maxn];
bool chk[maxn*10];
int g[1010][1010];
int n,k;
bool SearchPath(int u)
{
int v;
for(v=1;v<=n;v++)//是n还是k ,wa-re死了
{
if(g[u][v]&&!chk[v])
{
chk[v]=true;
if(yM[v]==-1||SearchPath(yM[v]))
{
yM[v]=u;
xM[u]=v;
return true;
}
}
}
return
false;
}
int MaxMatch()
{
int
u,ret=0;
memset(xM,-1,sizeof(xM));
memset(yM,-1,sizeof(yM));
for(u=1;u<=n;u++)//是n还是k,wa-re死了
{
if(xM[u]==-1)
{
memset(chk,false,sizeof(chk));
if(SearchPath(u))
{
ret++;
}
}
}
return
ret;
}
int main()
{
//int
n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
//memset(chk,false,sizeof(chk));
//scanf("%d%d",&uN,&vN);
//uN=n;
//vN=k;
int x,y;
memset(g,0,sizeof(g));
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
g[x][y]=1;
}
printf("%d\n",MaxMatch());
}
return
0;
}
Asteroids
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10532 | Accepted: 5687 |
Bessie wants to
navigate her spaceship through a dangerous asteroid field in the
shape of an N x N grid (1 <= N <= 500). The grid contains K
asteroids (1 <= K <= 10,000), which are conveniently located
at the lattice points of the grid.
Fortunately, Bessie has a powerful weapon that can vaporize all the
asteroids in any given row or column of the grid with a single
shot.This weapon is quite expensive, so she wishes to use it
sparingly.Given the location of all the asteroids in the field,
find the minimum number of shots Bessie needs to fire to eliminate
all of the asteroids.
Input
* Line 1: Two
integers N and K, separated by a single space.
* Lines 2..K+1: Each line contains two space-separated integers R
and C (1 <= R, C <= N) denoting the row and column
coordinates of an asteroid, respectively.
Output
* Line 1: The
integer representing the minimum number of times Bessie must
shoot.
Sample Input
3 4 1 1 1 3 2 2 3 2
Sample Output
2
Hint
INPUT DETAILS:
The following diagram represents the data, where "X" is an asteroid
and "." is empty space:
X.X
.X.
.X.
OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and
(1,3), and then she may fire down column 2 to destroy the asteroids
at (2,2) and (3,2).
Source
USACO 2005 November Gold
题意:
解题思路:
把方阵看做一个特殊的二分图(以行列分别作为两个顶点集V1、V2,其中| V1|=| V2|)
然后把每行x或者每列y看成一个点,而障碍物(x,y)可以看做连接x和y的边。按照这种思路构图后。问题就转化成为选择最少的一些点(x或y),使得从这些点与所有的边相邻,其实这就是最小点覆盖问题。
再利用二分图最大匹配的König定理:
最小点覆盖数 = 最大匹配数
(PS:最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖图的所有的边。)
因此本题自然转化为求 二分图的最大匹配 问题
求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。但是这个算法的时间复杂度为边数的指数级函数。
因此,需要寻求一种更加高效的算法——用增广路求最大匹配的方法(匈牙利算法)
增广路的定义(也称增广轨或交错轨):
若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。
由增广路的定义可以推出下述三个结论:
1、P的路径个数必定为奇数,第一条边和最后一条边都不属于M。
2、将M和P进行取反操作可以得到一个更大的匹配M’
(反操作:把P中的 匹配边 与 非匹配边 互换)
3、M为G的最大匹配当且仅当不存在M的增广路径P
匈牙利算法轮廓:
(1)置M为空
(2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M
(3)重复(2)操作直到找不出增广路径为止
其实就是求最大匹配,自己在图上模拟下就知道了。。
因为对模版的理解不到位导致wa-re了无数次。。
代码1:(以前做的),建议代码2
#include
#include
using namespace std;
#define MAXN 10010
int map[502][502];
int vis[MAXN],flag[MAXN];
int n,m;
bool dfs(int a)//寻找从a出发的对应项出的可增广路
{
int i;
for(i=1;i<=n;i++)//从邻接表中列举a能关联到顶点i
{
if(map[a][i]&&!vis[i])//i不在增广路上
{
vis[i]=1;//把i加入增广路;
if(flag[i]==0||dfs(flag[i]))//i是未盖点
或者 从i的对应项出发有可增广路
{
flag[i]=a;//修改i的对应项为a;
return
true;//则从i的对应项出有可增广路,返回true
}
}
}
return false;
}
int main()
{
int i;
while(cin>>n>>m)//n图的大小n*n,m个点(行星)
{
memset(map,0,sizeof(map));
for(i=1;i<=m;i++)
{
int
x,y;
cin>>x>>y;
map[x][y]=1;
}
memset(flag,0,sizeof(flag));
int result=0;
for(i=1;i<=n;i++)//void
匈牙利hungary()
{
memset(vis,0,sizeof(vis));
if(dfs(i))//则从i的对应项出有可增广路
result++;//匹配数++;
}
cout<<result<<endl;//输出
匹配数;
}
return 0;
}
代码2:套模版
#include
#include
#include
using namespace std;
const int maxn=10010;
int uN,vN;
int xM[maxn],yM[maxn];
bool chk[maxn*10];
int g[1010][1010];
int n,k;
bool SearchPath(int u)
{
int v;
for(v=1;v<=n;v++)//是n还是k ,wa-re死了
{
if(g[u][v]&&!chk[v])
{
chk[v]=true;
if(yM[v]==-1||SearchPath(yM[v]))
{
yM[v]=u;
xM[u]=v;
return true;
}
}
}
return
false;
}
int MaxMatch()
{
int
u,ret=0;
memset(xM,-1,sizeof(xM));
memset(yM,-1,sizeof(yM));
for(u=1;u<=n;u++)//是n还是k,wa-re死了
{
if(xM[u]==-1)
{
memset(chk,false,sizeof(chk));
if(SearchPath(u))
{
ret++;
}
}
}
return
ret;
}
int main()
{
//int
n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
//memset(chk,false,sizeof(chk));
//scanf("%d%d",&uN,&vN);
//uN=n;
//vN=k;
int x,y;
memset(g,0,sizeof(g));
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
g[x][y]=1;
}
printf("%d\n",MaxMatch());
}
return
0;
}
相关文章推荐
- [poj3041]Asteroids(二分图的最小顶点覆盖)
- poj3041 - Asteroids (二分图最小顶点覆盖)
- POJ3041 Asteroids (最小顶点覆盖)
- poj3041-Asteroids , 二分图的最小顶点覆盖数 = 最大匹配数
- poj3041 二分图最小顶点覆盖
- poj3041 Asteroids(最小顶点覆盖经典模型)
- POJ3041 Asteroids 二分图最小顶点覆盖 Dinic求解最大流
- POJ3041.Asteroids——最小顶点覆盖
- poj3041 二分图最小顶点覆盖
- poj3041-Asteroids , 二分图的最小顶点覆盖数 = 最大匹配数
- POJ3041 最小顶点覆盖
- POJ3041 最小顶点覆盖
- 【bzoj 1735】Muddy Fields 泥泞的牧场(最小割/最小顶点覆盖)
- 【二分匹配入门专题1】G - Asteroids poj3041【最小顶点覆盖】
- POJ3041最小点覆盖
- POJ2226(最小顶点覆盖)
- 图论中 [ 最小边覆盖/最小路径覆盖/最小顶点覆盖/最大独立集/最大团 ] 的概念与性质
- UVA 1292 - Strategic game(最小顶点覆盖问题,覆盖所有边,自己版本待解)
- hdu1054——Strategic Game(最小顶点覆盖+邻接表)
- POJ2226 不错的最小顶点覆盖