HDU 1054 Strategic Game(最小路径覆盖)

题目链接: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\n",max_match()/2);
    }
    return 0;
}

 

posted @ 2018-04-11 00:24  Yeader  阅读(232)  评论(0编辑  收藏  举报