题意:
给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个。答案每次加上两个选定的叶子之间的距离。求最后答案的最大值。
思路
首先,距离树上的任意一个节点最远的节点一定是某条直径的某个端点。
首先求出树的某一条直径,令其端点分别为L, R。把L看成树的根,那么R一定是叶子结点。对于那些非直径上的点,离他们最远的点肯定是L或R中的一个(可能也有其他的,但是L或R肯定已经最大了)。所以依次把这些非直径上的点删掉,删掉的时候在L和R中选择一个就行了。最后把直径删掉即可。
求直径可以两次bfs求,第一次从任意一个节点开始bfs,得到距离这个节点最远的那个节点一定是某条直径的某个端点,把这个端点记作p1,然后再从p1开始bfs,再求得该直径的另一个端点p2,然后直径就出来了。
代码写的很乱......
最开始写的代码,一直wa2,本地测试的结果和交上去的不一样,让希哥哥来找一下错误,发现是比较 ans1[x] 和 ans2[y] 的大小时写成了 ans1 和 ans2 ,然后改了一下,过了第2组数据,但是wa33,发现数据很大,爆 int 了,然后把结果改成 long long,还是 wa33,然后把所有数据类型全改成 long long ,过了。
希哥哥还是强啊
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
//#define inf 0x3f3f3f3f//1e9+6e7
#define inf 1000000000000000000
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
const int N=200010;
ll n,m;
ll tot=0;
ll ver[N<<1],nex[N<<1],head[N],vis[N];
ll ans1[N],ans2[N];
ll a[N];
ll d[N],d1[N],d2[N];
ll p1,p2;
ll pre[N];
void add(ll x,ll y)
{
ver[++tot]=y;
nex[tot]=head[x];
head[x]=tot;
}
ll bfs(ll p)
{
rep(i,0,n)
{vis[i]=0;d[i]=inf;}
queue<ll> q;
while(!q.empty())
q.pop();
q.push(p);
vis[p]=1;
d[p]=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
for(ll i=head[x];i;i=nex[i])
{
ll y=ver[i];
d[y]=min(d[y],d[x]+1);
if(vis[y]==0)
{vis[y]=1;q.push(y);}
}
}
ll maxx=-1,ret;
rep(i,1,n)
{
if(d[i]>maxx)
{
ret=i;
maxx=d[i];
}
}
return ret;
}
void bfs1(ll p)
{
rep(i,1,n)
{ans1[i]=inf;vis[i]=0;}
queue<ll> q;
q.push(p);
vis[p]=1;
ans1[p]=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
vis[x]=1;
for(ll i=head[x];i;i=nex[i])
{
ll y=ver[i];
ans1[y]=min(ans1[y],ans1[x]+1);
if(vis[y]==0)
q.push(y);
}
}
}
void bfs2(ll p)
{
rep(i,1,n)
{ans2[i]=inf;vis[i]=0;}
queue<ll> q;
q.push(p);
vis[p]=1;
ans2[p]=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
vis[x]=1;
for(ll i=head[x];i;i=nex[i])
{
ll y=ver[i];
ans2[y]=min(ans2[y],ans2[x]+1);
if(vis[y]==0)
q.push(y);
}
}
}
void bfss()
{
queue<ll> q;
q.push(p1);
rep(i,1,n)
{vis[i]=0;d[i]=inf;}
vis[p1]=1;
d[p1]=0;
while(!q.empty())
{
ll x=q.front();
q.pop();
vis[x]=1;
for(ll i=head[x];i;i=nex[i])
{
ll y=ver[i];
if(d[y]>d[x]+1)
{
d[y]=d[x]+1;
pre[y]=x;
}
if(vis[y]==0)
q.push(y);
}
}
}
void dfss(ll x)
{
vis[x]=1;
ll f=0;
for(ll i=head[x];i;i=nex[i])
{
ll y=ver[i];
if(y==p2)
{f++;continue;}
if(vis[y]==0)
{f++;dfss(y);}
}
if(f==0||a[x]==0)
{
if(ans1[x]>ans2[x])
cout<<p1<<" "<<x<<" "<<x<<endl;
else
cout<<p2<<" "<<x<<" "<<x<<endl;
return ;
}
}
int main()
{
cin >> n;
m=n-1;
ll x,y;
rep(i,1,m)
{
cin >> x >> y;
add(x,y);
add(y,x);
}
p1=bfs(1);
p2=bfs(p1);
// cout<<"*****"<<p1<<" "<<p2<<endl;
bfs1(p1);
bfs2(p2);
rep(i,1,n)
a[i]=0;
a[p1]=1;
a[p2]=1;
bfss();
ll pp=p2;
while(pre[pp]!=pp)
{
a[pre[pp]]=1;
pp=pre[pp];
}
ll ans=0;
ll cnt=0;
rep(i,1,n)
{
if(a[i])
{cnt++;continue;}
ans+=max(ans1[i],ans2[i]);
}
ans+=(cnt*(cnt-1)/2);
cout<<ans<<endl;
rep(i,1,n)
vis[i]=0;
dfss(p1);
pp=p2;
rep(i,1,cnt-1)
{
cout<<p1<<" "<<pp<<" "<<pp<<endl;
pp=pre[pp];
}
return 0;
}