来源:JZOJ
题目描述
大神 给定一棵 个点的边权树,由于他太强了,所以他想考考你。
让你求树中每个子树的最长链是多长?次长链是多长?(链可以长度为零,最长和次长链不能有相同的边)
备注,这里的链是子树中 根到节点的路径长度
解题思路
- 题目要求我们求最长链和次长链,当然最长链就直接迭代就好了,次长链如何求?其实,当最长链更新时,原本的最长链就是当前的次长链;但当最长链没有更新的情况下,次长链有可能可以更新,所以仍然要迭代;
-
表示以
为根的最长链
表示以 为根的次长链 - 因为是树结构,所以根 的最长链只可能与它的儿子有关;
代码君
#include <bits/stdc++.h>
using namespace std;
int dis[200010],dis2[200010],linkk[200010];
int t=0,n,st;
struct node
{
int y,v,next;
}e[200010];
void insert(int x,int y,int v)
{
e[++t].y=y; e[t].v=v;
e[t].next=linkk[x]; linkk[x]=t;
}
void dfs(int x,int father)
{
for (int i=linkk[x];i;i=e[i].next) //邻接表查询
{
int y=e[i].y;
if (y!=father)
{
dfs(y,x);
if(dis[y]+e[i].v>dis[x]) //更新最长链
{
dis2[x]=dis[x]; //用最长链更新次长链
dis[x]=dis[y]+e[i].v;
}
else
if(dis[y]+e[i].v<dis[x] && dis[y]+e[i].v>dis2[x]) //更新次长链
dis2[x]=dis[y]+e[i].v;
}
}
}
int main()
{
freopen("T4.in","r",stdin);
freopen("T4.out","w",stdout);
int T;
scanf("%d",&T);
for (int k=1;k<=T;k++)
{
memset(dis,0,sizeof(dis));
memset(dis2,0,sizeof(dis2));
memset(linkk,0,sizeof(linkk));
t=0;
scanf("%d %d",&n,&st);
for (int i=1;i<n;i++)
{
int x,y,v;
scanf("%d %d %d",&x,&y,&v);
insert(x,y,v); //邻接表插入
insert(y,x,v);
}
dfs(st,0);
for (int i=1;i<=n;i++) printf("%d ",dis[i]); //打印
printf("\n");
for (int i=1;i<=n;i++) printf("%d ",dis2[i]);
printf("\n");
}
return 0;
}