[Explanations] CJOI2019 chicken thief tree (structure title)

[Explanations] CJOI2019 chicken thief tree (structure title)

A chicken thief \ (n-\) tree nodes.
Chicken thief think this tree is too unsafe, because each edge is cutting edge, any thief stole the ball side of a tree can make this tree does not even
pass. In order to protect this tree, chicken thief decided to add some edge, so that the tree becomes a weightless edge, self-view of a ring, and delete any one side
after it still Unicom.
However, each adding an edge, have a fee. Chicken thief would like to save enough money to buy a Play Station 4, so he wanted to know, at least you want to add
the number of edges plus it? Of course, just knowing the number is not enough, in some test point, he wanted to know how to add edges.

The answer is clearly the optimal lower bound is \ (\ lfloor \ dfrac {C} + 1 2 \ rfloor \) , \ (C \) is the number of leaf nodes (not guarantee a degree of root). (Consider: Stop the parent side of a leaf node)

Consider such a configuration method, and a leaf node is connected to its \ (the LCA \) is another root node, the remaining one point is added even to the root. Find a root node, so that it is within each sub-tree leaf node is less than \ (\ lfloor \ dfrac {c + 1} 2 \ rfloor \)

Direct request \ (DFS \) sequence, the resulting leaves were added array \ (VE \) , the \ (ve [i] \) and \ (ve [i + \ lfloor \ dfrac {c + 1} 2 \ rfloor] \ ) connection, if the extra connection to the root node.

Obviously \ (ve [i] \) and \ (ve [i + \ lfloor \ dfrac {c + 1} 2 \ rfloor] \) a \ (the LCA \) is the root.

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=5e5+5;
int dr[maxn];
struct E{
      int to,nx;
      E(){to=nx=0;}
      E(const int&a,const int&b){to=a;nx=b;}
}e[maxn<<1];
vector<int> ve;
int head[maxn];
int n,rt,ans,op,cnt;
inline void add(const int&fr,const int&to,const int&b){
      e[++cnt]=E(to,head[fr]);
      head[fr]=cnt;
      ++dr[fr];
      if(dr[fr]>1)rt=fr;
      if(b)add(to,fr,0);
}

void dfs(const int&now,const int&last){
      if(dr[now]==1) ve.push_back(now);
      for(register int t=head[now];t;t=e[t].nx)
        if(e[t].to!=last) dfs(e[t].to,now);
}

int main(){
      //freopen("tree.in","r",stdin);
      //freopen("tree.out","w",stdout);
      n=qr();op=qr();
      for(register int t=1;t<n;++t) add(qr(),qr(),1);
      dfs(rt,0);
      int sz=ve.size();
      printf("%d\n",(sz+1)>>1);
      if(!op)return 0;
      for(register int t=0;t<(sz>>1);++t)
        printf("%d %d\n",ve[t],ve[t+(sz>>1)]);
      if(sz&1) printf("%d %d",ve[sz-1],rt);
      return 0;
}

Guess you like

Origin www.cnblogs.com/winlere/p/11299132.html