HYSBZ 3124 直径

题意:

Xiao Q has recently learned some graph theory. According to the textbook, there are the following definitions. Tree: a connected, undirected graph with no loops, each edge has a positive integer weight to indicate its length. If a tree has N nodes, it can be proved that it has and has only N-1 edges. Path: There is at most one simple path between any two nodes on a tree. We use dis (a, b)
Represents the sum of the lengths of the sides on the path of points a and b. We call dis (a, b) the distance between two nodes a and b.
Diameter: The longest path on a tree is the diameter of the tree. The diameter of the tree may not be unique.
Now Q wants to know, for a given tree, what is the length of its diameter, and how many edges satisfy all diameters passing through that edge.

Input:

The first line contains an integer N, which represents the number of nodes.
The next N-1 lines, each with three integers a, b, c, means that there is a length c between point a and point b
Undirected edge.

Output:

There are two lines. The first line is an integer representing the length of the diameter. The second line is an integer indicating that all
The number of sides that the diameter passes through.


   C
   |
A--B--D----E----F         // 假设这是一棵树
           |
           |
           G

第一问随便做,这里讲第二问

我们先随便找一条直径比如在本图中,我们假设是 A-B-D-E-F

然后我们把这条直径上所有的点都求出来,看成一条链,然后分成两部分,比如这里可以分成 A-B 和 D-E-F

我们先处理 A-B 这条链,对于这个链上的每个点我们都要这么处理:
找一下是否存在不走直径方向能达到的一个点使得从这个点走到那个点的路径等于这个点走到左端点的路径,如果存在,那么就把左边界设置为这个点

我来具体解释一下:假设我们现在要处理 B 点,我们不走直径方向,也就是不走 A 方向和 D 方向,然后我们往C走到底,发现 B-C 的距离刚好等于 B-A ,那就说明什么?直径这里既可以是 A-B ,也可以是 B-C ,那么一定会经过的点的左边界由 A 更改为 B。

对于右边那条链也是一样处理方法

然后最后输出链上共同属于左边界和右边界中间的点有几个就行了

// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
#define int long long
using namespace std;
const int MaxN=200050;
struct Edge
{
    int nxt,to,w;
}E[MaxN<<2];
template <class t> inline void read(t &s)
{
    s=0;
    reg int f=1;
    reg char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while(isdigit(c))
        s=(s<<3)+(s<<1)+(c^48),c=getchar();
    s*=f;
    return;
}
int hd[MaxN],en,n;
int dis[MaxN];
int plist[MaxN],pn;
bool inzj[MaxN];
int cost[MaxN];
inline void adde(int u,int v,int w)
{
    ++en;
    E[en]=(Edge){hd[u],v,w};
    hd[u]=en;
    return;
}
inline void dfs1(int u,int fa)
{
    for(int i=hd[u];~i;i=E[i].nxt)
    {
        reg int v=E[i].to;
        if(v==fa)
            continue;
        dis[v]=dis[u]+E[i].w;
        dfs1(v,u);
    }
    return;
}
inline bool dfs2(int u,int fa,int ed)
{
    if(u==ed)
    {
        plist[++pn]=u;
        inzj[u]=true;
        return true;
    }
    for(int i=hd[u];~i;i=E[i].nxt)
    {
        reg int v=E[i].to;
        if(v==fa)
            continue;
        if(dfs2(v,u,ed))
        {
            plist[++pn]=u;
            cost[pn-1]=E[i].w;
            inzj[u]=true;
            return true;
        }
    }
    return false;
}
inline bool dfs3(int u,int fa,int nddis,int sum)
{
    if(sum==nddis&&!inzj[u])
        return true;
    for(int i=hd[u];~i;i=E[i].nxt)
    {
        reg int v=E[i].to;
        if(v==fa||inzj[v])
            continue;
        if(dfs3(v,u,nddis,sum+E[i].w))
            return true;
    }
    return false;
}
signed main(void)
{
    memset(hd,-1,sizeof hd);
    cin>>n;
    reg int u,v,w;
    for(int i=1;i<n;++i)
    {
        read(u);read(v);read(w);
        adde(u,v,w);
        adde(v,u,w);
    }
    reg int st=0,ed=0;
    {
        reg int maxi=0;
        dfs1(1,0);
        for(int i=2;i<=n;++i)
            if(dis[i]>maxi)
                st=i,maxi=dis[i];
        dis[st]=0;maxi=0;
        dfs1(st,0);
        for(int i=1;i<=n;++i)
            if(dis[i]>maxi)
                ed=i,maxi=dis[i];
    }
    dfs2(st,0,ed);
    /*
    {
        puts("ZhiJing:");
        for(int i=1;i<=pn;++i)
            printf("%d ",plist[i]);
        puts("");
    }
    */
    reg int eL=pn/2;
    reg int sR=pn/2+1;
    reg int L=1,R=pn;
    reg int sumDis=0;
    for(int i=1;i<=eL;++i)
    {
        if(dfs3(plist[i],0,sumDis,0))
            L=i;
        sumDis+=cost[i];
    }
    sumDis=0;
    for(int i=pn;i>=sR;--i)
    {
        if(dfs3(plist[i],0,sumDis,0))
            R=i;
        sumDis+=cost[i-1];
    }
    {
        reg int sum=0;
        for(int i=1;i<pn;++i)
            sum+=cost[i];
        printf("%lld\n",sum);
    }
    printf("%lld\n",max(0ll,R-L));
    // printf("%lld %lld\n",plist[L],plist[R]);
    // printf("LR %lld %lld\n",L,R);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/chinesepikaync/p/12426154.html