正题
nowcoder 20107-C
题目大意
给一棵树,让你构造一个序列a,使得a中的数互不相等,且相邻点是祖先的关系,回答序列最长长度
解题思路
书中的每个点可以把字数的两个序列连起来
考虑维护一个堆,存子树中的序列,每次从子树中找两个最大的序列,然后合并起来,其他的上传到当前堆,这里合并堆可以用启发式合并
code
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100100
#define ll long long
using namespace std;
int T,n,x,y,tot,h[N],hs[N],sz[N],to[N];
priority_queue<int>d[N];
struct rec
{int to,nx;
}e[N<<1];
void add(int x,int y)
{e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return;
}
void dfs(int x,int fa)
{hs[x]=0;sz[x]=1;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y==fa)continue;dfs(y,x);sz[x]+=sz[y];if(sz[y]>sz[hs[x]])hs[x]=y;}if(hs[x])to[x]=to[hs[x]];for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y==fa||y==hs[x])continue;while(!d[to[y]].empty())d[to[x]].push(d[to[y]].top()),d[to[y]].pop();//上传}if(d[to[x]].size()>=2){int g1=d[to[x]].top();//找最大的两个d[to[x]].pop();int g2=d[to[x]].top();d[to[x]].pop();d[to[x]].push(g1+g2+1);}else if(d[to[x]].size()>=1){int g1=d[to[x]].top();d[to[x]].pop();d[to[x]].push(g1+1);}else d[to[x]].push(1);return;
}
int main()
{scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=1;i<=n;++i)to[i]=i;tot=0;memset(h,0,sizeof(h));for(int i=1;i<n;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);printf("%d\n",d[to[1]].top());for(int i=1;i<=n;++i)while(!d[to[i]].empty())d[to[i]].pop();}return 0;
}