poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

http://poj.org/problem?id=3041

在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利用这个武器摧毁所有的小行星最少需要几发光束.

主要是构图,将每一行当成一个点,构成集合1,每一列也当成一个点,构成集合2,每一个障碍物的位置坐标将集合1和集合2的点连接起来,也就是将每一个障碍物作为连接节点的边,这样可以得出本题是一个最小点覆盖的问题==二分图的最大匹配.

就可以通过匈牙利算法求解。

邻接表实现 0ms.

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 class edge{
 6 public:
 7     int v,nex;
 8 };
 9 edge e[10001];
10 int n,m,k,head[10001];
11 int link[501];
12 bool vis[501];
13 
14 void init()
15 {
16     k=0;
17     memset(head,0,sizeof(head));
18 }
19 void addedge(int b,int a)
20 {//向图中加边的算法,注意加上的是有向边//b为a的后续节点既是a---->b
21     e[k].v=a;
22     e[k].nex=head[b];
23     head[b]=k;k++;
24 }
25 bool dfs(int u){
26     for(int i = head[u]; i != 0; i = e[i].nex){
27         int v = e[i].v;
28         if(!vis[v]){
29             vis[v] = true;
30             if(link[v] == -1 || dfs(link[v])){
31                 link[v] = u;
32                 return true;
33             }
34         }
35     }
36     return false;
37 }
38 int main()
39 {
40     int u,v;
41     scanf("%d%d",&n,&m);
42     init();
43     for(int i=0;i<m;i++)
44     {
45         scanf("%d%d",&u,&v);
46         addedge(v-1,u-1);
47     }
48     int ans=0;
49     memset(link,-1,sizeof(link));
50     for(int i = 0; i < n; i ++){
51         memset(vis,0,sizeof(vis));
52         if(dfs(i)) ans++;
53     }
54     printf("%d\n", ans);
55     return 0;
56 }

邻接矩阵:

 1 #include <cstdio>
 2 #include <cstring>
 3 const int MAXN=501;
 4 int uN,vN;  //u,v数目
 5 int g[MAXN][MAXN];//编号是0~n-1的
 6 int linker[MAXN];
 7 bool used[MAXN];
 8 bool dfs(int u)
 9 {
10     int v;
11     for(v=0;v<uN;v++)
12         if(g[u][v]&&!used[v])
13         {
14             used[v]=true;
15             if(linker[v]==-1||dfs(linker[v]))
16             {
17                 linker[v]=u;
18                 return true;
19             }
20         }
21     return false;
22 }
23 int hungary()
24 {
25     int res=0;
26     int u;
27     memset(linker,-1,sizeof(linker));
28     for(u=0;u<uN;u++)
29     {
30         memset(used,0,sizeof(used));
31         if(dfs(u))  res++;
32     }
33     return res;
34 }
35 
36 int main()
37 {
38     int u,v;
39     scanf("%d%d",&uN,&vN);
40     memset(g,0,sizeof(g));
41     while(vN--)
42     {
43         scanf("%d%d",&u,&v);
44         g[u-1][v-1]=1;
45     }
46     printf("%d\n",hungary());
47     return 0;
48 
49 }

 

posted @ 2015-06-09 19:49  NowAndForever  阅读(180)  评论(0编辑  收藏  举报