Briefly meaning of the questions:
Given a tree, find the longest "fob" length.
Lanyards defined: on one strand spanning all the nodes connected thereto configuration. (Non-strict definitions) (the original title is "Caterpillar", I thought lanyards more images)
This problem has a variety of approaches, here are ideas, as well as one of the code of practice.
A algorithm
Notes that, in fact, we only need to select the "longest chain", then both sides can lanyards in the longest chain.
That is, first find the tree diameter two endpoints, and the endpoints traverse over the diameter, the edges thereof are added directly connected spanning tree.
The answer to the last statistics.
time complexity: .
Expectations rating: .
Algorithms two
Consider the tree , with Expressed is the maximum root length lanyards, recording number of his son, then:
Obviously, the answer to either the direct successor son node, or to both sides of a fight.
time complexity: .
Expectations rating: .
Algorithm for Three
Gives one of the most ingenious algorithm.
Hypothesis of the number of points is , The length of a lanyards answer should be:
represents belong to the current chain, i.e., the side removed to give double counting the number of edges, and obtained points. Simplification namely:
You find this thing a little ugly, so for a moment:
Clearly, the reduced inside each node, each dotted Ge.
Then we can solve the following steps:
-
Build a statistical chart and degrees .
-
Diameter at both ends is obtained.
-
All of the nodes on the statistical diameter, then is the answer.
time complexity: .
Actual score: .
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+1;
inline int read(){char ch=getchar();int f=1; while(!isdigit(ch)) {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}
int n,m,du[N],dis[N];
int num,mx;
vector<int> G[N];
inline void dfs(int dep,int fa,int dis) {
//fa 是 dep 的父亲 , dep 是正在搜索的节点,dis 是它与开始搜索节点的距离,dis 统计度和
if(dis>mx) mx=dis,num=dep; //度和打擂
for(int i=0;i<G[dep].size();i++)
if(G[dep][i]!=fa) dfs(G[dep][i],dep,dis+du[dep]); //往下搜索
}
int main(){
n=read(),m=read();
memset(du,-1,sizeof(du)); //初始化为 -1, 即减掉 1
while(m--) {
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
du[x]++; du[y]++; //统计度
} dfs(1,0,du[1]); mx=0;
dfs(num,0,du[num]); //两次 dfs 寻找直径
printf("%d\n",mx+2); // +2 就是答案
return 0;
}