直径 HYSBZ - 3124

https://www.lydsy.com/JudgeOnline/problem.php?id=3124

第一问求树的直径 第二问求有多少边被所有直径覆盖

求第一问时把直径上的点存下来 枚举直径上的点 求一下不走直径上的点所能到达的最远距离 记为dis3 如果和直径的左端点距离相等 就把当前点到左端点的边都标记 这些边就是不符合条件的 和直径的右端点距离相等同样处理

要求的边时被所有直径覆盖的 如果有某个点的dis3等于到左右端点的距离 说明存在另外一条直径 该点到端点上的这些边没有被另外一条直径覆盖

复杂度还是o(n)的 因为不能走直径就相当于把这颗树分成了很多不连通的小部分 非直径上的点只会被走一次

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct node
{
    int v;
    ll w;
    int next;
};

node edge[400010];
ll dis1[200010],dis2[200010],dis3[200010];
int first[200010],fa1[200010],fa2[200010],book[200010],pre[200010];
int n,num;

void addedge(int u,int v,ll w)
{
    edge[num].v=v;
    edge[num].w=w;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfsI(int cur,int &p)
{
    ll w;
    int i,v;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v,w=edge[i].w;
        if(v!=fa1[cur])
        {
            dis1[v]=dis1[cur]+w,fa1[v]=cur;
            dfsI(v,p);
            if(dis1[p]<dis1[v]) p=v;
        }
    }
}

void dfsII(int cur)
{
    ll w;
    int i,v;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v,w=edge[i].w;
        if(v!=fa2[cur])
        {
            dis2[v]=dis2[cur]+w,fa2[v]=cur;
            dfsII(v);
        }
    }
}

void dfsIII(int cur,ll &maxx)
{
    ll w;
    int i,v;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v,w=edge[i].w;
        if(book[v]==0)
        {
            dis3[v]=dis3[cur]+w,book[v]=1;
            maxx=max(maxx,dis3[v]);
            dfsIII(v,maxx);
        }
    }
}

int main()
{
    ll w,maxx,ans1;
    int i,j,u,v,p1,p2,p,ans2;
    scanf("%d",&n);
    memset(first,-1,sizeof(first));
    num=0;
    for(i=1;i<=n-1;i++)
    {
        scanf("%d%d%lld",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }

    dis1[1]=0,fa1[1]=0;
    p1=0;
    dfsI(1,p1);
    dis1[p1]=0,fa1[p1]=0;
    p2=0;
    dfsI(p1,p2);
    ans1=dis1[p2];
    //printf("***%d %d***\n",p1,p2);

    dis2[p2]=0,fa2[p2]=0;
    dfsII(p2);

    p=p1,num=0;
    while(p!=0)
    {
        pre[++num]=p;
        book[p]=1;
        p=fa2[p];
    }

    p=p1;
    while(p!=0)
    {
        dis3[p]=0;
        maxx=0;
        dfsIII(p,maxx);
        dis3[p]=maxx;
        p=fa2[p];
    }

    /*
    printf("***%d***\n",num);
    for(i=1;i<=num;printfi++)
    {
        printf("*%d %lld %lld %lld*\n",pre[i],dis1[pre[i]],dis2[pre[i]],dis3[pre[i]]);
    }
    */

    memset(book,0,sizeof(book));
    for(i=1;i<=num;i++)
    {
        if(dis3[pre[i]]==dis1[pre[i]]) for(j=i-1;j>=1&&book[j]==0;j--) book[j]=1;
    }
    for(i=num;i>=1;i--)
    {
        if(dis3[pre[i]]==dis2[pre[i]]) for(j=i;j<=num-1&&book[j]==0;j++) book[j]=1;
    }

    ans2=0;
    for(i=1;i<=num-1;i++) ans2+=(book[i]==0);

    printf("%lld\n%d\n",ans1,ans2);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82498342