首页 > 代码库 > 【最小点覆盖】POJ3041-Asteroids

【最小点覆盖】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 }

 

【最小点覆盖】POJ3041-Asteroids