[CF911F]Tree Destruction

题目大意:
  给你一棵树,每次选取其中的两个叶子结点,往答案中加上它们的距离,并删去其中一个结点。
  你可以自由进行上述操作,使得最后答案最大。
  问答案最大是多少,并输出其中一种方案。

思路:
  贪心。
  首先找出树的直径,然后枚举直径外的叶子结点。
  看一下该结点到直径两端距离哪个长,并加上这个距离。
  删去这个点。
  最后按顺序删直径上的点。
  每次存一下方案,最后直接输出即可。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 typedef long long int64;
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=200001;
13 std::vector<int> e[N];
14 inline void add_edge(const int &u,const int &v) {
15     e[u].push_back(v);
16     e[v].push_back(u);
17 }
18 bool mark[N];
19 int u,v,disu[N]={-1},disv[N]={-1},from[N],seq[N];
20 void dfs1(const int &x,const int &par) {
21     disv[x]=disv[par]+1;
22     if(disv[x]>disv[u]) u=x;
23     for(unsigned i=0;i<e[x].size();i++) {
24         const int &y=e[x][i];
25         if(y==par) continue;
26         dfs1(y,x);
27     }
28 }
29 void dfs2(const int &x,const int &par) {
30     from[x]=par;
31     seq[++seq[0]]=x;
32     disu[x]=disu[par]+1;
33     if(disu[x]>disu[v]) v=x;
34     for(unsigned i=0;i<e[x].size();i++) {
35         const int &y=e[x][i];
36         if(y==par) continue;
37         dfs2(y,x);
38     }
39 }
40 void dfs3(const int &x,const int &par) {
41     disv[x]=disv[par]+1;
42     for(unsigned i=0;i<e[x].size();i++) {
43         const int &y=e[x][i];
44         if(y==par) continue;
45         dfs3(y,x);
46     }
47 }
48 struct Answer {
49     int a,b,c;
50 };
51 Answer ans[N];
52 int cnt;
53 int main() {
54     const int n=getint();
55     for(register int i=1;i<n;i++) {
56         add_edge(getint(),getint());
57     }
58     dfs1(1,0);
59     dfs2(u,0);
60     dfs3(v,0);
61     for(register int i=v;i;i=from[i]) mark[i]=true;
62     int64 sum=0;
63     for(register int i=seq[0];i;i--) {
64         const int x=seq[i];
65         if(mark[x]) continue;
66         if(disu[x]>disv[x]) {
67             ans[cnt++]=(Answer){u,x,x};
68             sum+=disu[x];
69         } else {
70             ans[cnt++]=(Answer){v,x,x};
71             sum+=disv[x];
72         }
73     }
74     for(register int i=v;i!=u;i=from[i]) {
75         ans[cnt++]=(Answer){u,i,i};
76         sum+=disu[i];
77     }
78     printf("%I64d
",sum);
79     for(register int i=0;i<cnt;i++) {
80         printf("%d %d %d
",ans[i].a,ans[i].b,ans[i].c);
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/skylee03/p/8175737.html