1207. 大臣的旅费

树的直径 = 所有点的最长链+次长链的最大值

优质题解

树型dp

某个点的最长链 = 连接该点和其子节点的边 + 子节点的最大值。
很像dfs。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2e5+10;
struct edge{
    int v,next,w;
}e[N];
int cnt = 0;
int n,ans = 0;
int head[N];
void add(int u,int v,int w)
{
    e[cnt].v = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt++;
}
//树的直径 = 所有边里的最长边 + 次长边  
int dfs(int u,int father)   //返回到u的最长的边
{
    int d1 = 0,d2 = 0; //d1是最大边,d2是次大边
    for(int i=head[u];~i;i=e[i].next)
    {
        int v = e[i].v,w = e[i].w;
        if(v==father) continue; //防止回溯
        int d = dfs(v,u) + w;   //d是儿子节点的最长边 + 当前节点和儿子节点的和,表示最长边
        if(d > d1) {d2 = d1; d1 = d;}
        else if(d > d2) d2 = d;
        
    }
    ans = max(ans,d1+d2);
    return d1;
}
int main()
{
    cin>>n;
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    dfs(1,-1);
    printf("%lld",ans*10 +1ll*(ans+1)*ans / 2);
}

两次dfs

  1. 对任意一个点dfs,找出到该点距离最大的点,则该点为树的直径的一个端点。
  2. 再从该点重复dfs,找到到该点距离最大的点,则这两个点即树的直径的两个端点。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define x first
#define y second
using namespace std;
struct edge{
    int v,w;
};
const int N = 100010;
vector<edge> G[N];
int n;
int dist[N];    //dis[i]表示 dfs(u) u到其他点的距离。
void dfs(int u,int father,int dis)
{
    dist[u] = dis;
    for(int i=0;i<G[u].size();i++)
    {
        int v = G[u][i].v;
        if(v!=father)   //防止回溯
        {
            dfs(v,u,dis+G[u][i].w);
        }
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        G[u].push_back({v,w});
        G[v].push_back({u,w});
    }

    dfs(1,-1,0);
    int u = 1;
    for(int i=1;i<=n;i++)
        if(dist[i] > dist[u])
            u=i;

    dfs(u,-1,0);
    long long res = 0;
    for(int i=1;i<=n;i++)
        res = max(res,1ll*dist[i]);
    printf("%lld",(res*res+21ll*res)/2);
}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐