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