You are given a forest — an undirected graph with nn vertices such that each its connected component is a tree.
The diameter (aka "longest shortest path") of a connected undirected graph is the maximum number of edges in the shortest path between any pair of its vertices.
You task is to add some edges (possibly zero) to the graph so that it becomes a tree and the diameter of the tree is minimal possible.
If there are multiple correct answers, print any of them.
Input
The first line contains two integers nn and mm (1≤n≤10001≤n≤1000, 0≤m≤n−10≤m≤n−1) — the number of vertices of the graph and the number of edges, respectively.
Each of the next mm lines contains two integers vv and uu (1≤v,u≤n1≤v,u≤n, v≠uv≠u) — the descriptions of the edges.
It is guaranteed that the given graph is a forest.
Output
In the first line print the diameter of the resulting tree.
Each of the next (n−1)−m(n−1)−m lines should contain two integers vv and uu (1≤v,u≤n1≤v,u≤n, v≠uv≠u) — the descriptions of the added edges.
The resulting graph should be a tree and its diameter should be minimal possible.
For m=n−1m=n−1 no edges are added, thus the output consists of a single integer — diameter of the given tree.
If there are multiple correct answers, print any of them.
Examples
input
Copy
4 2
1 2
2 3
output
Copy
2
4 2
input
Copy
2 0
output
Copy
1
1 2
input
Copy
3 2
1 3
2 3
output
Copy
2
Note
In the first example adding edges (1, 4) or (3, 4) will lead to a total diameter of 3. Adding edge (2, 4), however, will make it 2.
Edge (1, 2) is the only option you have for the second example. The diameter is 1.
You can't add any edges in the third example. The diameter is already 2.
大意:
给你一个森林 其中每棵树有自己的直径 要你把森林的每棵树都连成一棵新树 让新生成的树直径最小
一棵树是一个无向无环图
一个森林则是若干个不连通的树组成的图
树的直径的定义是一棵树中任意两顶点间的最短路中最长的一条
思路:
对于森林里的每一棵树,找到一个顶点,使得该点与树上任意一点的最大距离最小,该点为中心。(一棵树可能有2个中心,取任意一个),找到直径最大的一棵树,将该树的中心与其他树的中心连接起来。 令树t1,t2的中心为u,v,diam1为t1的直径,diam2为t2直径,d1为u到t1上任意一点的最大距离,d2为v到t2上任意一点的最大距离,那么连接两棵树后可得到的最小直径是 d=max(diam1,diam2,d1+d2+1), 使d1,d2最小则可得到最小的d
#include<bits/stdc++.h>
using namespace std;
const int maxn=200*1000+13;
const int INF=0x3f3f3f3f;
int n,m;
vector<int>g [maxn];
int bfs(int x,int dist[maxn]){
queue<int> q;
q.push(x);
dist[x]=0;
int lst=-1;
while(!q.empty()){
int v=q.front();
q.pop();
lst=v;
for (auto u : g[v]) if (dist[u] > dist[v] + 1){
dist[u]=dist[v]+1;
q.push(u);
}
}
return lst;
}
int distFromX[maxn],distFromY[maxn];
bool used[maxn];
vector<int> cur;
void dfs(int x){
used[x]=true;
cur.push_back(x);
for(auto u:g[x]) if(!used[u]) dfs(u);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int v,u;
scanf("%d%d",&v,&u);
v--;u--;
g[v].push_back(u);
g[u].push_back(v);
}
for(int i=0;i<n;i++) distFromX[i]=distFromY[i]=INF;
vector<pair<int,int>>comps;
for(int i=0;i<n;i++) if(!used[i]){
cur.clear();
dfs(i);
int x=bfs(i,distFromY); //find the position of x
int y=bfs(x,distFromX);
for(auto u:cur) distFromY[u]=INF;
bfs(y,distFromY); //update distFromY array
int d=distFromX[y],center;
for(auto u:cur) if(distFromX[u]==d/2&&distFromY[u]==d-d/2)
center=u;
comps.push_back({d,center});
}
vector<pair<int,int>>ans;
nth_element(comps.begin(),comps.end()-1,comps.end());
int sz=comps.size()-1;
for(int i=0;i<sz;i++){
g[comps[i].second].push_back(comps.back().second);
g[comps.back().second].push_back(comps[i].second);
ans.push_back({comps[i].second,comps.back().second});
}
for(int i=0;i<n;i++) distFromX[i]=distFromY[i]=INF;
int y=bfs(bfs(comps.back().second,distFromY),distFromX);
printf("%d\n",distFromX[y]);
for(auto u:ans) printf("%d %d\n",u.first+1,u.second+1);
}