Gym 101612 Problem H. Hidden Supervisors(树,贪心)

题意:
有一棵树,1为根,有些点没有确定父节点。
一个数对代表父节点和一个儿子节点,每个节点只能选一次。
要求给没有确定父节点的点确定一个父节点,使得最后仍然是棵树,而且数对最多。

思路:
对每个连通块跑dfs,递归到最底层,如果父节点和儿子节点都没有标记,那就打上标记,向上回溯。这样能保证对于一个树得出最多的数对。

然后用一个vector维护根节点对应子树中所有没有用到的数对。
如果一个连通块根节点被用过,那就连上1;如果没有被用过,那就连上一个空闲节点。
最后把连通块内的空闲节点放入vector。

每次当然是用空闲节点最多的连通块,这样保证当前空闲节点相对更多。

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e5 + 7;

struct Node {
     
    int rt,len;
    vector<int>vec;
    bool operator < (const Node&rhs) const {
     
        return len > rhs.len;
    }
};

int fa[maxn],match[maxn];
vector<int>Q,now,G[maxn];
vector<Node>nodes;
int ans;

void dfs(int x){
     
    for(int i = 0;i < G[x].size();i++) {
     
        int v = G[x][i];
        dfs(v);
        if(!match[v] && !match[x]) {
     
            match[x] = match[v] = 1;
            ans++;
        }
        if(!match[v]) {
     
            now.push_back(v);
        }
    }
}

int main() {
     
    freopen("hidden.in","r",stdin);
    freopen("hidden.out","w",stdout);
    int n;scanf("%d",&n);
    for(int i = 2;i <= n;i++) {
     
        scanf("%d",&fa[i]);
        G[fa[i]].push_back(i);
    }
    
    for(int i = 1;i <= n;i++){
     
        if(!fa[i]) {
     
            now.clear();
            dfs(i);
            if(i == 1 || match[i]) {
     
                fa[i] = 1;
                for(int j = 0;j < now.size();j++) {
     
                    Q.push_back(now[j]);
                }
                if(i == 1 && !match[i]) {
     
                    Q.push_back(i);
                }
            } else {
     
                Node no;
                no.rt = i;
                no.len = now.size();
                no.vec = now;
                nodes.push_back(no);
            }
        }
    }
    
    sort(nodes.begin(),nodes.end());
    
    for(int i = 0;i < nodes.size();i++) {
     
        if(Q.size()) {
     
            ans++;
            int x = Q.back();
            fa[nodes[i].rt] = x;
            Q.pop_back();
        } else {
     
            fa[nodes[i].rt] = 1;
            Q.push_back(nodes[i].rt);
        }
        for(int j = 0;j < nodes[i].len;j++) {
     
            Q.push_back(nodes[i].vec[j]);
        }
    }
    
    printf("%d\n",ans);
    for(int i = 2;i <= n;i++) {
     
        printf("%d ",fa[i]);
    }
    return 0;
}

你可能感兴趣的:(#,gym)