码迷,mamicode.com
首页 > 其他好文 > 详细

[SDOI2013]直径 (树的直径,贪心)

时间:2018-08-20 22:59:43      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:c++   const   cout   problem   pac   getchar   space   getc   last   

题目链接


Solution

我们直接找到一条直径 \(s\),起点为 \(begin\),终点为 \(end\).
从前往后遍历点 \(u\) ,若子树中最大的距离与 \(dis(u,begin)\) 相等.
很显然这个点不在公共线段上,很显然可以用子树的中的一段接上,形成一条新的直径.
然后从后往前遍历,同样的道理...
然后找到两个节点 \(l,r\) 然后答案即为 \(r-l\).
记得要开 \(longlong\).


Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=300008;
struct sj{
ll to,next,w;
}a[maxn*2];
ll head[maxn],size;
ll n,s,x,y,w;
ll read()
{
    ll f=1,w=0; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
    return f*w;
}
void add(ll x,ll y,ll w)
{
    a[++size].to=y;
    a[size].next=head[x];
    head[x]=size;a[size].w=w;
}

ll last,num,now,cnt,v[maxn],bcnt;
ll ans[maxn],maxx,road[maxn];
ll dist[maxn],b[maxn],ansb[maxn];
ll sum[maxn];
void dfs(ll x)
{
    v[x]=1;
    road[++cnt]=x;
    for(ll i=head[x];i;i=a[i].next)
    {
         ll tt=a[i].to;
         if(!v[tt])
         {
            now+=a[i].w;
            b[++bcnt]=a[i].w;
            dfs(tt); cnt--;bcnt--;
            now-=a[i].w;
         }
    }
    if(now>maxx)
    {
        num=cnt; last=x; maxx=now;
        for(ll i=1;i<=cnt;i++)
        ans[i]=road[i],ansb[i]=b[i];
    }
}

void getdist(ll x)
{
    v[x]=1;
    maxx=max(maxx,now);
    for(ll i=head[x];i;i=a[i].next)
    {
        ll tt=a[i].to;
        if(!v[tt])
        {
            now+=a[i].w;
            getdist(tt);
            now-=a[i].w;
        }
    }
}

int main()
{
    n=read();
    for(ll i=1;i<n;i++)
    {
        x=read(); y=read(); w=read();
        add(x,y,w); add(y,x,w);
    }
    dfs(1);
    memset(v,0,sizeof(v));
    maxx=0; cnt=0; now=0;
    dfs(last);
    memset(v,0,sizeof(v));
    for(ll i=1;i<=num;i++)v[ans[i]]=1;
    for(ll i=2;i<=num;i++)sum[i]=sum[i-1]+ansb[i-1];
    for(ll i=1;i<=num;i++)
    {maxx=0,getdist(ans[i]),dist[i]=maxx;}
    
    ll l=1,r=num;
    for(int i=1;i<=num;i++)
    if(sum[i]==dist[i]) l=i;
    for(int i=num;i>=1;i--)
    if(sum[num]-sum[i]==dist[i]) r=i;
    cout<<sum[num]<<endl;
    cout<<r-l<<endl;
    
}

[SDOI2013]直径 (树的直径,贪心)

标签:c++   const   cout   problem   pac   getchar   space   getc   last   

原文地址:https://www.cnblogs.com/Kv-Stalin/p/9508261.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!