Gym101612H Hidden Supervisors

题目链接:https://vjudge.net/problem/Gym-101612H

知识点:  贪心

解题思路:

  我们称除了以 (1) 号结点为根的树以外的树为 “其他树”。

  对于每一棵树,先自底向上贪心地组队,记录下每一棵其他树没有组队的结点数及根结点是否有组队,然后对其他树进行排序(排序优先法则请参考 (cmp()) 函数)。

  对于根结点已经有组队的树,我们直接让根结点连接 (1) 号结点即可;对于根结点没有组队的树,我们可以让根结点连现有的树里面没有组队的结点(如果现有的树里面的结点都已经有组队了,则直接连接到 (1) 号结点)。这部分我选择用一个 (queue) 来维护现有的树中没有组队的结点。

AC代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 1e5+5;
  4 
  5 struct Node{
  6     int ID;
  7     bool HeadHave;
  8     int NoHave;
  9 };
 10 vector<int> to[maxn];
 11 bool rot[maxn],have[maxn];
 12 vector<Node> head;
 13 queue<int> notn;
 14 
 15 void dfs(int s){
 16     if(to[s].empty())
 17         return;
 18     for(int i=0;i<to[s].size();i++){
 19         dfs(to[s][i]);
 20         if(!have[to[s][i]]&&!have[s])
 21             have[s]=have[to[s][i]]=true;
 22     }
 23 }
 24 void dfs1(int s){
 25     if(!have[s])    notn.push(s);
 26     for(int i=0;i<to[s].size();i++){
 27         dfs1(to[s][i]);
 28     }
 29 }
 30 bool cmp(const Node &a,const Node &b){
 31     if(a.HeadHave&&!b.HeadHave) return true;
 32     else if(!a.HeadHave&&b.HeadHave)    return false;
 33     else{
 34         if(a.NoHave>b.NoHave)   return true;
 35         else    return false;
 36     }
 37 }
 38 int dfs2(int s){
 39     int ret=0;
 40     if(!have[s])    ret++;
 41     for(int i=0;i<to[s].size();i++)
 42         ret+=dfs2(to[s][i]);
 43     return ret;
 44 }
 45 
 46 int ans[maxn];
 47 int main(){
 48     freopen("hidden.in","r",stdin);
 49     freopen("hidden.out","w",stdout);
 50     int n;
 51     scanf("%d",&n);
 52     memset(rot,true,sizeof(rot));
 53     for(int i=1;i<n;i++){
 54         int x;
 55         scanf("%d",&x);
 56         if(x){
 57             to[x].push_back(i+1);
 58             ans[i+1]=x;
 59             rot[i+1]=false;
 60         }
 61     }
 62     Node tmp;
 63     for(int i=1;i<=n;i++){
 64         if(rot[i]){
 65             dfs(i);
 66             if(i!=1){
 67                 tmp.HeadHave=have[i];
 68                 tmp.ID=i;
 69                 tmp.NoHave=dfs2(i);
 70                 head.push_back(tmp);
 71             }
 72         }
 73     }
 74     sort(head.begin(),head.end(),cmp);
 75 
 76     dfs1(1);
 77     for(int i=0;i<head.size();i++){
 78         int id=head[i].ID;
 79         if(have[id]){
 80             ans[id]=1;
 81             dfs1(id);
 82         } else{
 83             if(notn.size()){
 84                 int x=notn.front();
 85                 notn.pop();
 86                 have[x]=have[id]=true;
 87                 ans[id]=x;
 88                 dfs1(id);
 89             } else{
 90                 ans[id]=1;
 91                 dfs1(id);
 92             }
 93         }
 94     }
 95     int has=0;
 96     for(int i=1;i<=n;i++){
 97         if(have[i]) has++;
 98     }
 99     printf("%d
",has/2);
100     for(int i=2;i<=n;i++){
101         if(i!=2)    printf(" ");
102         printf("%d",ans[i]);
103     }
104     printf("
");
105 
106     return 0;
107 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
原文地址:https://www.cnblogs.com/Blogggggg/p/9003551.html