树(1)最长边树
赛车
时间限制:20000ms
单点时限:1000ms
内存限制:256MB
描述
幻想乡有一个赛车场。赛车场里有N个地点。同时地点之间还有单向的道路存在。
这些道路使得赛车场形成了一个外向树的结构。也就是说,道路将这N个地点连成了一个有根树。并且所有的边都是从父亲指向孩子的。
由于幽香喜欢刺激,每次她去赛车场都会从根节点出发,选择最长的一条路径来玩。
但是现在幽香感觉最长的路径还是太短了,她打算在赛车场里新建一条道路使得新的最长路径最长。
同时,如果道路形成了一个环,那么可能会出现交通事故,所以幽香新建的道路不能导致环的出现。
你能帮幽香算出新建一条道路后的最长路径吗?幽香知道根节点一定是1号点。
输入
一行一个数N,表示地点的数量。
接下来N-1行,每行两个数a和b,表示从点a到点b有一条单向路径。所有点从1到n标号。
数据范围:
n<=100000。
输出
一行表示新建一条边后的最长路径。
- 样例输入
-
5 1 2 2 3 1 4 4 5
- 样例输出
-
4
首先遍历一棵树,dis[x]表示从x节点开始一条边上最多的节点数(包括x节点),比如1 2 ,2 3,dis[1] = 3,dis[2] = 2,dis[3] = 1。
自然,dis[1]就是最多边的节点数。
然后,再搜索一遍,将最多边上的节点标记vis[x] = 1;
再对没有标记过的节点vis[x] = 0,进行比较他们的dis[x]值,自然,找到最大的,便是要连的节点。
最后节点数-1便是answer。#include<cstdio> #include<vector> #include<algorithm> const int maxn = 1e5+5; using namespace std; vector<int>vec[maxn]; int dis[maxn]; bool vis[maxn]; int n; int build(int x){ if(vec[x].size()==0) return 1;//没有子节点了,反馈该节点数,也就是1。 for(int i = 0; i < vec[x].size(); i++) dis[x] = max(dis[x],build(vec[x][i])+1);//进行标记,找出最大dis[x];"+1"就是加x本身的节点数,自然是1。 return dis[x]; }
//从1开始进行搜索,根据最大的dis[x]进行进一步搜索,并且对每个搜索到的节点进行标记vis[x] = 1。 void findl(int x){ vis[x] = 1; if(vec[x].size()==0) return; int t = 0; for(int i = 1; i < vec[x].size(); i++){ if(dis[vec[x][i]] > dis[vec[x][t]]) t = i; } findl(vec[x][t]); } int main(){ int u,v; while(~scanf("%d",&n)){
//初始化。 for(int i = 1; i <= n; i++){ vec[i].clear(); dis[i] = 0; vis[i] = 0; }
//vector。 for(int i = 1; i < n; i++){ scanf("%d%d",&u,&v); vec[u].push_back(v); } int ans = build(1); findl(1); int maxx = 0;
//对没有标记的节点进行比较,找出最大dis[x]。 for(int i = 1; i <= n; i++){ if(!vis[i]) maxx = max(maxx,dis[i]); } printf("%d\n",ans+maxx-1); } return 0; }

浙公网安备 33010602011771号