您的位置:首页 > 其它

poj3041(最小顶点覆盖)

2013-05-30 11:07 148 查看
http://poj.org/problem?id=3041

Asteroids

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 10532Accepted: 5687
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

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: