codeforces 911 F. Tree Destruction

题目链接

题意:

给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个。答案每次加上两个选定的叶子之间的距离。求最后答案的最大值。

思路

首先,距离树上的任意一个节点最远的节点一定是某条直径的某个端点。

首先求出树的某一条直径,令其端点分别为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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值