【最小点覆盖】POJ3041-Asteroids

【题目大意】

在n*n的网格上有n个点,每次删除一行或者一列,问至少要删除几次才能删除完全部的这些店?

【思路】

在国庆最后一天到来前,把二分图的三个基本情况【最小点覆盖】【DAG图的最小路径覆盖】和【二分图的最大独立集】全部复习了一遍。

这道题是非常典型的最小点覆盖,指的是用最少的点让每条边都至少和两个集合中的某一个点关联。

最小点覆盖=二分图最大匹配数。

对于这道题而言,我们把横坐标作为集合X,纵坐标作为集合Y,对于点(x,y),由X中的x连向Y中的y。对于每条边,只要x和y中有一个被删除即可,明显的最小点覆盖模型。

十分钟水~

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 const int MAXN=505;
 8 vector<int> E[MAXN];
 9 int lk[MAXN],vis[MAXN],n,k; 
10 
11 int find(int u)
12 {
13     for (int i=0;i<E[u].size();i++)
14     {
15         int v=E[u][i];
16         if (!vis[v])
17         {
18             vis[v]=1;
19             if (!lk[v]||find(lk[v]))
20             {
21                 lk[v]=u;
22                 return 1;
23             }
24         }
25     }
26     return 0;
27 }
28 
29 void init()
30 {
31     scanf("%d%d",&n,&k);
32     for (int i=1;i<=k;i++)
33     {
34         int x,y;
35         scanf("%d%d",&x,&y);
36         E[x].push_back(y);
37     }
38 }
39 
40 void solve()
41 {
42     int ans=0;
43     memset(lk,0,sizeof(lk));
44     for (int i=1;i<=n;i++)
45     {
46         memset(vis,0,sizeof(vis));
47         if (find(i)) ans++;
48     }
49     printf("%d",ans);
50 } 
51 
52 int main()
53 {
54     init();
55     solve();
56     return 0;
57 }

 

posted @ 2016-10-06 22:42  iiyiyi  阅读(277)  评论(0编辑  收藏  举报