题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1054
题目大意:给你一棵树,选取树上最少的节点使得可以覆盖整棵树。
解题思路:
首先树肯定是二分图,因为树可以奇偶分层,从而根据二分图染色的原理可以确定树是二分图。
我们可以用染色法确定出两个集合求最大匹配,也可以将边补成双向的,然后将最大匹配/2。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int N=2e3+5; int n,m; int link[N]; bool vis[N]; vector<int>v[N]; bool dfs(int u){ for(int i=0;i<v[u].size();i++){ int t=v[u][i]; if(!vis[t]){ vis[t]=true; if(link[t]==-1||dfs(link[t])){ link[t]=u; return true; } } } return false; } int max_match(){ memset(link,-1,sizeof(link)); int ans=0; for(int i=0;i<n;i++){ memset(vis,false,sizeof(vis)); if(dfs(i)) ans++; } return ans; } int main(){ while(~scanf("%d",&n)){ for(int i=0;i<=n;i++) v[i].clear(); for(int i=1;i<=n;i++){ int num,cnt,x; scanf("%d:(%d)",&num,&cnt); for(int j=1;j<=cnt;j++){ scanf("%d",&x); v[num].push_back(x); v[x].push_back(num); } } //最小点覆盖,由于对该二分图进行了补全(无向图),边增加为原来边的二倍。所以最终结果要除以2 printf("%d ",max_match()/2); } return 0; }