题目链接:点击查看

题目大意:给出 n 个点组成的一棵树,每个节点都有一个权值,现在规定权值相同的节点之间,简单路径的边数为 x ,求 x * x 的最大值

题目分析:真的很巧,上周刚学的虚树,读完这个题的第一反应就是可以用虚树简化题目,其实完全可以用树形dp跑一遍dfs出来,可奈何我dp不好,就只能用虚树来做了

题目中有两个点可以单独考虑,首先是权值相同的点,这个就可以用虚树将权值相同的点都拎出来,然后是简单路径的边数最大,这个对应着树的直径,所以直接虚树配合树的直径写一个dfs,直接维护最大值就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>pos[N];bool cmp(int x,int y);struct virtual_tree
{//原树部分 struct{int to,next;}edge[N<<1];int head[N],cnt,deep[N],dp[N][20],limit;//树上倍增int L[N],R[N],dfn;//dfs序 void addedge(int u,int v){edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}void dfs(int u,int fa,int dep){L[u]=++dfn;deep[u]=dep;dp[u][0]=fa;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(v!=fa)dfs(v,u,dep+1);}R[u]=dfn;}int LCA(int x,int y){if(deep[x]<deep[y])swap(x,y);for(int i=limit;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=limit;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0];}void init(int n){memset(head,-1,sizeof(head));cnt=dfn=0;limit=log2(n)+1;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}}//虚树部分 vector<int>node[N];vector<int>ver;int Stack[N];void build(){sort(ver.begin(),ver.end(),cmp);int sz=ver.size()-1;for(int i=0;i<sz;i++)ver.push_back(LCA(ver[i],ver[i+1]));sort(ver.begin(),ver.end(),cmp);ver.erase(unique(ver.begin(),ver.end()),ver.end());int top=0;Stack[++top]=ver[0];for(int i=1;i<ver.size();i++){while(top&&R[Stack[top]]<L[ver[i]])top--;if(top)node[Stack[top]].push_back(ver[i]);Stack[++top]=ver[i];}}void clear(){for(int i=0;i<ver.size();i++)node[ver[i]].clear();ver.clear();}int d[N],ans;void dfs(int u,int fa){d[u]=0;for(auto v:node[u]){if(v==fa)continue;dfs(v,u);int w=deep[v]-deep[u];ans=max(ans,d[v]+d[u]+w);d[u]=max(d[u],d[v]+w);}}LL solve(int val){ver=pos[val];build();//建虚树 ans=0;dfs(ver.front(),-1);//树形dp求树的直径 clear();//初始化 return ans;}
}tree;bool cmp(int x,int y)
{return tree.L[x]<tree.L[y];
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<=n;i++){int num; scanf("%d",&num);pos[num].push_back(i);}tree.init(n);tree.dfs(1,0,0);LL mmax=0;for(int i=1;i<=n;i++)if(pos[i].size())mmax=max(mmax,tree.solve(i));printf("%lld\n",mmax*mmax);return 0;
}

牛客 - 王国(虚树+树的直径)相关推荐

  1. 树的距离(牛客网树上主席树+dfs序)

    链接:https://ac.nowcoder.com/acm/problem/14415 来源:牛客网 题目描述 wyf非常喜欢树.一棵有根数树上有N个节点,1号点是他的根,每条边都有一个距离,而wy ...

  2. 刷题记录:牛客NC53074Forsaken喜欢独一无二的树

    传送门:牛客 题目描述: 众所周知,最小生成树是指使图中所有节点连通且边权和最小时的边权子集. 不过最小生成树太简单了,我们现在来思考一个稍微复杂一点的问题. 现在给定一个n个点,m条边的图,每条边e ...

  3. 牛客 - 点对最大值(树的直径)

    题目链接:点击查看 题目大意:给出 n 个点组成的一棵树,每个点和每条边都有权值,现在需要求出一对点 ( x , y ) ,使得点 x 到点 y 的唯一路径权值和最大,权值和包括点 x 和点 y 的权 ...

  4. 牛客网 桃花(树的直径)

    桃花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 桃花一簇开无主,可爱深红映浅红. - ...

  5. 牛客 - sequence(笛卡尔树+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a 和数列 b ,求 题目分析:不算难的题目,对于每个 a[ i ] 求一下贡献然后维护最大值就好,具体思路就是,先找出每个 a[ i ] 左 ...

  6. 牛客 - 骚区间(线段树+思维)

    题目链接:点击查看 题目大意:给出一个 1 ~ n 的排列 a ,现在规定骚区间当且仅当 a[ l ] 是 [ l , r ] 这段区间内的次小值,同时 a[ r ] 是 [ l , r ] 这段区间 ...

  7. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  8. 牛客练习赛52 BGalahad 树状数组

    传送门 题意: 求一个区间的和,但如果某一个数在这个区间出现了多次,这个数只能被计算一次. 官方题解:按右端点从小到大排序.建立树状数组ccc,维护贡献的前缀和. 由于权值ai 满足1≤ai≤500  ...

  9. 【哈夫曼树】牛客 哈夫曼树

    题目描述 哈夫曼树,第一行输入一个数n,表示叶结点的个数.需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和. 输入描述: 输入 ...

最新文章

  1. golang获取md5
  2. [蓝桥杯][算法提高VIP]分分钟的碎碎念(dfs)
  3. shell管道重定向程序的实现
  4. 第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波5 - 分段线性变换 - 灰度级分层
  5. linux下重新启动oracle
  6. 【华为云技术分享】ARM体系结构基础(3)
  7. Linux开机启动过程(7):内核执行入口点
  8. MVC4网站发布到windows server 2003服务器
  9. python语音合法命名-下列哪些语句在Python中是合法的( )
  10. 【转】C++实用技巧(三)
  11. 信息安全密码学期末复习重点总结
  12. 程序员如何成为架构师
  13. 180822 逆向-网鼎杯(2-1)
  14. I want to be a teacher when I grow up ——长大后我想当老师
  15. 外设驱动库开发笔记42:DAC8552 DAC驱动
  16. Android霓虹灯文字控件
  17. Ubuntu_部分键盘F1~F12强制为功能键
  18. PHP电商运费模板,电商系统设计之运费模板(下)
  19. 联想笔记本安装PHP环境,联想笔记本装系统步骤 教你如何正确安装笔记本系统...
  20. jetson nano补充:根目录/usr刷机扩容 瘦身

热门文章

  1. java term_[ElasticSearch]Java API 之 词条查询(Term Level Query)
  2. Nacos源码NacosAutoServiceRegistration
  3. SpringSecurity分布式整合之认证服务配置文件编写和测试
  4. Nginx安装方式介绍
  5. Collections集合工具类的方法_sort(List)
  6. SpringBoot_入门-HelloWorld细节-场景启动器(starter)
  7. SpringBoot_入门-课程简介
  8. oracle解析select,oracle_select语句例子解析
  9. 验证哥德巴赫猜想:任何一个大于6的偶数均可表示为2个素数之和
  10. Asp.NetCore-部署到IIS