Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes' numbers.
For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print "Error: K components" where K is the number of connected components in the graph.
5<br/>1 2<br/>1 3<br/>1 4<br/>2 5
3<br/>4<br/>5
来自博客http://blog.csdn.net/sinat_29278271
# include <cstdio> # include <iostream> # include <cstring> # include <algorithm> # include <set> # include <vector> using namespace std; const int size = 10000; const int debug = 1; class DisjointSet { private: int *T,size,sum; int FindRoot(int i){return T[i] < 0 ? i : (T[i] = FindRoot(T[i]));} public: DisjointSet(int _size):size(_size) { T = new int[size]; Init(); } void Init(){sum = size;memset(T,-1,sizeof(int)*size);} bool Unioned(int i,int j){return FindRoot(i)==FindRoot(j);} void Union(int i,int j) { if ( (i = FindRoot(i) ) != ( j = FindRoot(j) ) ) { T[i] = T[i] + T[j]; T[j] = i; sum--; } } int FindSum(int i){return -T[FindRoot(i)];} int SumOfUnits(){return sum;} ~DisjointSet(){delete[] T;} }; vector<int> v[size]; int vis[size]; void dfs(int i,int dist,int &MAX) { vis[i] = dist; MAX = max(MAX,vis[i]); for (int k=0;k<v[i].size();k++) if (vis[v[i][k]]==-1) dfs(v[i][k],dist+1,MAX); } int main() { int i,j,temp; int n; scanf("%d",&n); DisjointSet ds(n); for (i=0;i<n-1;i++) { int a,b; scanf("%d%d",&a,&b);a--,b--; v[a].push_back(b); v[b].push_back(a); ds.Union(a,b); } if (ds.SumOfUnits() == 1) { int start,Max; set<int> s; for (Max=start=i=0;i<2;i++) { memset(vis,-1,sizeof(vis)); dfs(start,0,Max); for (j=0;j<n;j++) if (vis[j]==Max) s.insert(j); start = *s.begin(); } for (set<int>::iterator it = s.begin();it!=s.end();it++) printf("%d\n",(*it)+1); } else printf("Error: %d components\n",ds.SumOfUnits()); return 0; }
从任意一个节点开始进行深度优先遍历,找到离他最远的节点(可能不止一个,记为集合A);第二步:再从A中任意选一个节点出发进行深度优先遍历,找到离他最远的节点(记为集合B),最后最深根就是这两个集合的并集。
证明:第一步找出的节点一定是全局的最深根。
1 根据全局最优解一定是局部最优解的原理:最后全局的最深根一定也是某个局部最优解,比如:因为全局最深的根是固定的,不失一般性,我们就把他们标为1、2、3、4、5,那么从图中中任意一点出发,例如A,从他出发找到的局部最优解一定是在1、2、3、4、5,反之,如不在,也就是说有比1、2、3、4、5更深的节点,我们假设它存在并且成为B,那么可想而知,从1到B肯定要比从1到2要深,这就与1、2、3、4、5是全局最优解矛盾,所以假设不成立。原命题成立。即局部最优解一定在1、2、3、4、5中。
2 由第一步知道局部最优解是固定的,且全局最优解是局部最优解,根据这两条结论,得出:第一次遍历得到的最深的节点就是最深根
package go.jacob.day1017; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; /** * 1021. Deepest Root (25) * * @author Jacob 一共N个点,有N-1条边。只要components大于1,必定有环。 * 寻找最远距离的时候,只要使用两次DFS就可以了。原因如下: 树中最远的距离必是距离根节点R最远和次远的两个叶节点的连线。 * 可以任意选择一个节点,进行深度优先搜索,第一次找到最远的节点。 用刚刚找到的最远节点为根节点做dfs,再次寻找最远节点(可能有多个) */ public class Demo1 { static int components = 0; static int n; static ArrayList<Integer>[] matrix; static boolean[] visited; static int[] deep; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); matrix = new ArrayList[n + 1]; for (int i = 1; i < n + 1; i++) { matrix[i] = new ArrayList<Integer>(); } visited = new boolean[n + 1]; deep = new int[n + 1]; for (int i = 0; i < n - 1; i++) { int a = sc.nextInt(), b = sc.nextInt(); matrix[a].add(b); matrix[b].add(a); } for (int i = 1; i < n + 1; i++) { if (!visited[i]) { dfs(i, i); components++; } } if (components == 1) {// 说明输入正常 Queue<Integer> queue = new LinkedList<Integer>(); ArrayList<Integer> list = new ArrayList<Integer>(); queue.add(1); initVisited(visited); visited[1] = true; int max = getDeep(queue, 1); // 找到最远节点,加入到list中 for (int i = 1; i < n + 1; i++){ if (deep[i] == max){ list.add(i); } } initVisited(visited); max = list.get(0); visited[max] = true; queue.add(max); max = getDeep(queue, max); for (int i = 1; i < n + 1; i++){ if (deep[i] == max && !list.contains(i)){ list.add(i); } } Collections.sort(list); for (Integer v : list) System.out.println(v); } else { System.out.println("Error: " + components + " components"); } sc.close(); } /* * 获得当前树的最深深度 */ private static int getDeep(Queue<Integer> queue, int end) { int level = 1; int tmpEnd=end; while (!queue.isEmpty()) { int tmp = queue.poll(); for (Integer v : matrix[tmp]) { if (!visited[v]) { deep[v] = level; queue.offer(v); visited[v] = true; tmpEnd=v; } } if (!queue.isEmpty()&&tmp == end) { end = tmpEnd; level++; } } return level-1; } /* * 初始化visited矩阵(设置为false) */ private static void initVisited(boolean[] visited2) { for (int i = 1; i < n + 1; i++) visited[i] = false; } /* * 深度优先搜索 */ private static void dfs(int root, int pre) { visited[root] = true; for (Integer temp : matrix[root]) { if (temp.equals(pre)) continue; if (!visited[temp]) dfs(temp, root); } } }
#include <cstdio> #include <vector> #include <string.h> using namespace std; const int MAXN=1e4+10; int n; vector<int> vex[MAXN]; bool visited[MAXN]={false},vis[MAXN]; int dfs(int root,int depth){ int d,maxd=depth; vis[root]=true; for(int i=0;i<vex[root].size();++i) if(!vis[vex[root][i]]){ d=dfs(vex[root][i],depth+1); if(maxd<d) maxd=d; } return maxd; } void dfs2(int root){ visited[root]=true; for(int i=0;i<vex[root].size();++i) if(!visited[vex[root][i]]) dfs2(vex[root][i]); } int main() { int a,b; scanf("%d",&n); if(n==1){printf("1");return 0;} for(int i=1;i<n;++i){ scanf("%d%d",&a,&b); vex[a].push_back(b); vex[b].push_back(a); } int cnt=0,depth,maxdepth=-1; vector<int> MaxDVex; for(int i=1;i<=n;++i) if(!visited[i]){ dfs2(i); ++cnt; } if(cnt>1) printf("Error: %d components",cnt); else{ for(int i=1;i<=n;++i){ memset(vis,0,sizeof(vis)); if(!vis[i] && vex[i].size()==1){ ++cnt; depth=dfs(i,1); if(maxdepth<depth){ maxdepth=depth; MaxDVex.clear(); MaxDVex.push_back(i); }else if(maxdepth==depth) MaxDVex.push_back(i); } } for(int i=0;i<MaxDVex.size();++i) printf("%d\n",MaxDVex[i]); } return 0; }
#include<string>
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
int findRoot2(int *tree,int i)
{
if(tree[i]==-1)return i;
else
{
int tmp = findRoot2(tree,tree[i]);
tree[i]=tmp;
return tmp;
}
}
int maxlevel =0;
void dfs(vector<int> *result,int level,int startNode,bool *already)
{
//if(result[startNode].size()<=0) return;
already[startNode] = true;
if(maxlevel<level)
{
maxlevel = level;
}
for(int i=0;i<result[startNode].size();i++)
{
if(!already[result[startNode][i]])
{
int current = level+1;
dfs(result,current,result[startNode][i],already);
}
}
}
int main()
{
int N;
scanf("%d",&N);
int *tree = new int[N+1];
vector<int> *result = new vector<int>[N+1];
for(int i=1;i<=N;i++)
{
tree[i]=-1;
}
if(N==1)
{
int a,b;
scanf("%d %d",&a,&b);
cout<<a<<endl;
return 0;
}
for(int i=1;i<=N-1;i++)
{
int a,b;
scanf("%d %d",&a,&b);
result[a].push_back(b);
result[b].push_back(a);
a=findRoot2(tree,a);
b=findRoot2(tree,b);
if(a!=b)
{
tree[a]=b;
}
}
int sum=0;
for(int j=1;j<=N;j++)
{
if(tree[j]==-1)
sum++;
}
map<int,vector<int>> deep;
bool *already = new bool[N+1];
if(sum>1)
{
cout<<"Error: "<<sum<<" components"<<endl;
return 0 ;
}
else
{
//寻找最大的深度的root id
for(int i=1;i<=N;i++)
{
//深度遍历叶结点
if(result[i].size()==1)
{
maxlevel = 1;
for(int k=1;k<=N;k++)
{
already[k]=false;
}
already[i]=true;
dfs(result,0,i,already);
deep[maxlevel].push_back(i);
}
}
}
int max=0;
for(map<int,vector<int>>::iterator it=deep.begin();it!=deep.end();it++)
{
if(it->first>max)
{
max=it->first;
}
}
sort(deep[max].begin(),deep[max].end());
for(int i=0;i<deep[max].size();i++)
{
cout<<deep[max][i]<<endl;
}
return 0;
}
//方法1(此方法在数据量大时会超时)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10010;
vector<int> Adj[maxn],ans;
bool vis[maxn]={false};
int n,v1,v2,temp,block,deepest=0;
void DFS(int u,int depth){
vis[u]=true;
if(depth>temp) temp=depth; //temp为当前点i为根时的最大深度
for(int i=0;i<Adj[u].size();i++){
int v=Adj[u][i];
if(vis[v]==false)
DFS(v,depth+1);
}
}
void DFSTrave(int root){
DFS(root,1); //从当前点i(传入为root)开始遍历
block++;
for(int u=1;u<=n;u++){
if(vis[u]==false){
DFS(u,1);
block++;
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n-1;i++){
scanf("%d%d",&v1,&v2);
Adj[v1].push_back(v2);
Adj[v2].push_back(v1);
}
for(int i=1;i<=n;i++){
temp=0;
block=0;
fill(vis,vis+maxn,false);
DFSTrave(i); //每次从不同点开始遍历
if(block==1){ //n个点n-1条边的连通图必为树
if(temp==deepest) ans.push_back(i); //本次遍历得到的树深度与最大深度相同
else if(temp>deepest){
deepest=temp;
ans.clear();
ans.push_back(i);
}
}
else{ //若图不连通
printf("Error: %d components\n",block);
break;
}
}
if(ans.size()!=0){
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
cout<<ans[i]<<endl;
}
return 0;
}
//方法2 //全局最优解是局部最优解,第一次遍历得到的最深的结点就是最深根 //由于从最深根出发到最深的叶子节点是相互对称的,所以我们再从当前的最深根出发遍历一次得到其他的最深根,再去重。 #include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=10010;
vector<int> Adj[maxn],temp,ans;
set<int> s; //用set不用排序,不用去重
bool vis[maxn]={false};
int n,v1,v2,block=0,deepest=0;
void DFS(int u,int depth){
vis[u]=true;
if(depth==deepest) ans.push_back(u);
else if(depth>deepest){ //若当前深度比最大树高大
deepest=depth;
ans.clear();
ans.push_back(u);
}
for(int i=0;i<Adj[u].size();i++){
int v=Adj[u][i];
if(vis[v]==false)
DFS(v,depth+1);
}
}
void DFSTrave(int root){
DFS(root,1); //从当前点i(传入为root)开始遍历
block++;
for(int u=1;u<=n;u++){
if(vis[u]==false){
DFS(u,1);
block++;
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n-1;i++){
scanf("%d%d",&v1,&v2);
Adj[v1].push_back(v2);
Adj[v2].push_back(v1);
}
DFSTrave(1); //先从点1开始一次遍历
if(block==1){ //n个点n-1条边的连通图必为树
temp=ans; //让temp先保存第一次遍历时离根最远的结点集合
ans.clear();
fill(vis,vis+maxn,false);
DFSTrave(temp[0]); //从任意一个第一次遍历所得的最远结点开始第二次遍历
}
else { //若图不连通
printf("Error: %d components\n",block);
return 0;
}
for(int i=0;i<temp.size();i++) //将两次遍历所得的结点插入set中(自动去重并排序)
s.insert(temp[i]);
for(int i=0;i<ans.size();i++)
s.insert(ans[i]);
for(auto i=s.begin();i!=s.end();i++)
cout<<*i<<endl;
return 0;
}
// 1021_Deepest_Root.cpp: 定义控制台应用程序的入口点。 // #include <set> #include <vector> #include <iostream> #include <algorithm> using namespace std; //----------定义图 struct vexNode { vector<int> Edge; }; vector<vexNode> G; int cnt; //结点计数 bool *visit;// 访问数组 int *h;// 每个结点为根的 高度数组 int highest=0;//最高用于比较 void Dfs(int s,int h,int&hest) { if (visit[s] == true) { return; } visit[s] = true; if (h > hest) {// DFS 求最大深度 hest = h; } for (int i = 0; i < G[s].Edge.size(); i++) { if (visit[G[s].Edge[i]] == false) { Dfs(G[s].Edge[i],h+1,hest); } } } int DFSTravle(int s, int &high) {// 在对整张图dfs 的过程中求连通分量。 int components = 0;// 联通分量 if (visit[s] == false) {// 先从起始点开始一次dfs Dfs(s, 1, high); components++; } int t = 0; for (int i = 1; i <= cnt; i++)// 在对整张图dfs 求得连通分量 { if (visit[i] == false) { Dfs(i, 1, t); components++; } } return components; } int main() { cin >> cnt; for (int i = 0; i <=cnt; i++) { G.push_back(vexNode()); } for (int i = 0; i < cnt-1; i++) { int f, t; cin >> f >> t; G[f].Edge.push_back(t); G[t].Edge.push_back(f); } visit = new bool[cnt+1]; h = new int[cnt+1]; for (int i = 1; i <=cnt; i++) { h[i] = 0; } for (int i = 1; i <=cnt; i++) {// 对没个结点都做一次DFS for (int j = 1; j <=cnt; j++) { visit[j] = false; } int comp = DFSTravle(i,h[i]);// 得到连通分量和 对应节点的最高的深度 if (comp!= 1) { //多个连通分liang cout << "Error: " << comp << " components"; return 0; } } vector<int> high; int best = -1; for (int i = 1; i <= cnt; i++) {// 选出最大深度的结点(多个 ) if (h[i] >= best) { if (h[i] > best) { high.clear(); } high.push_back(i); best = h[i]; } } vector<int>::iterator it = high.begin(); for (; it != high.end(); it++) { cout << *it << endl; } return 0; }
//两次dfs就能确定所有的最深结点 #include <cstdio> #include <vector> #include <cstring> #include <set> using namespace std; const int maxn = 10000 + 10; vector<int> graph[maxn]; int fa[maxn], visited[maxn] = {0}; int height[maxn] = {0}, max_height = 0; set<int> out_node; void init(int num){ for(int k=1; k<=num; k++) fa[k] = k; } int find_fa(int x){ while(x != fa[x]) x = fa[x]; return x; } void Union(int x, int y){ x = find_fa(x); y = find_fa(y); if(x != y) fa[x] = y; } int Components_num(int num){ set<int> s; for(int i=1; i<=num; i++){ int set_id = find_fa(i); if(s.count(set_id) == 0) s.insert(set_id); } return s.size(); } void Dfs(int s){ visited[s] = 1; for(unsigned int i=0; i<graph[s].size(); i++){ int v = graph[s][i]; if(visited[v]) continue; height[v] = height[s] + 1; max_height = (max_height > height[v]) ? max_height : height[v]; Dfs(v); } } int main(){ int n; scanf("%d", &n); init(n); for(int i=0; i<n-1; i++){ int u, v; scanf("%d %d", &u, &v); graph[u].push_back(v); graph[v].push_back(u); Union(u, v); } int cnm = Components_num(n); if(cnm > 1) printf("Error: %d components\n", cnm); else{ height[1] = 0; Dfs(1); for(int i=1; i<=n; i++){ if(height[i] == max_height) out_node.insert(i); } max_height = 0; memset(height, 0, sizeof(height)); memset(visited, 0, sizeof(visited)); int s = *(out_node.begin()); Dfs(s); for(int i=1; i<=n; i++){ if(height[i] == max_height) out_node.insert(i); } for(auto iter=out_node.begin(); iter!=out_node.end(); iter++) printf("%d\n", *iter); } return 0; }
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
using namespace std;
const int maxn=10005;
vector<int> map[maxn]; //邻接表
//**************并查集计算连通图个数****************//
int father[maxn];
//*****************初始化并查集*****************//
void init(int n){
for (int i=0; i < n; ++i) {
father[i] = i;
}
}
//********************查找根节点*******************//
int getfather(int x){
if (x != father[x]) {
father[x] = getfather(father[x]);
}
return father[x];
}
//*********合并两个元素所在的集合,返回是否有环*********//
void Union(int x,int y){
x = getfather(x);
y = getfather(y);
if (x != y) {
father[x] = y;
}
}
//*****************并查集结束****************//
//*************DFS**************//
vector<int> visited;
int deepest;
set<int> res;
void DFS(int i,int distance){
if (distance > deepest) {
res.clear();
res.insert(i);
deepest = distance;
}
else if (distance == deepest){
res.insert(i);
}
visited[i] = 1;
for (int j=0; j < map[i].size(); ++j) {
if (!visited[map[i][j]]) {
visited[map[i][j]] = 1;
DFS(map[i][j],distance+1);
visited[map[i][j]] = 0;
}
}
visited[i] = 0;
}
int main(){
int N,from,to;
cin >> N;
init(N); //初始化并查集
for (int i=1; i < N; ++i) {
cin >> from >> to;
Union(from,to);
map[from].push_back(to);
map[to].push_back(from);
}
int Sum_huan = 0; //连通分量的个数
for (int i=1; i < N; ++i) {
if (father[i]==i) {
Sum_huan++;
}
}
visited.resize(N+1, 0);
if (Sum_huan > 1) {
cout << "Error: " << Sum_huan << " components" <<endl;
return 0;
}
set<int> trees;
//****************随便找个点1开始第一次深度搜索找到最远的点*****************//
DFS(1, 1);
//******************第一次找到的点一定是最后需要的那个根节点之一*************//
for (auto it = res.begin(); it != res.end(); ++it) {
trees.insert(*it);
}
//****************从最远的点开始第二次搜索******************//
int point = (*res.begin());
DFS(point, 1);
for (auto it = res.begin(); it != res.end(); ++it) {
trees.insert(*it);
}
for (auto it = trees.begin(); it != trees.end(); ++it) {
cout << *it << endl;
}
return 0;
}
#include<bits/stdc++.h> using namespace std; const int Max=10010; int father[Max]; int height[Max]; int n; vector<int> G[Max],tmp,ans; void Initial() { for(int i=1; i<=n; i++) { father[i]=i; height[i]=1; } } int Find(int x) { if(x!=father[x]) { father[x]=Find(father[x]); } return father[x]; } void Union(int x,int y) { x=Find(x); y=Find(y); if(x!=y) { if(height[x]>height[y]) { father[y]=x; } else if(height[x]<height[y]) { father[x]=y; } else { father[x]=y; height[y]++; } } } int Maxh=0; void DFS(int id,int h,int f) { if(h>Maxh) { tmp.clear(); tmp.emplace_back(id); Maxh=h; } else if(h==Maxh) { tmp.emplace_back(id); } for(int i=0; i<G[id].size(); i++) { if(G[id][i]==f) continue; DFS(G[id][i],h+1,id); } } int main() { int a,b; scanf("%d",&n); Initial(); for(int i=1; i<n; i++) { scanf("%d %d",&a,&b); G[a].emplace_back(b); G[b].emplace_back(a); Union(a,b); } int count=0; for(int i=1; i<=n; i++) { if(i==Find(i)) { count++; } } if(count>1) { printf("Error: %d component\n",count); return 0; } else { DFS(1,1,-1); ans=tmp; DFS(ans[0],1,-1); for(int i=0; i<tmp.size(); i++) { ans.emplace_back(tmp[i]); } sort(ans.begin(),ans.end()); printf("%d\n",ans[0]); for(int i=1; i<ans.size(); i++) { if(ans[i]!=ans[i-1]) printf("%d\n",ans[i]); } } return 0; }
#include<iostream> #include<string> #include<map> #include<vector> #include<set> #include<queue> #include<algorithm> #include<bits/stdc++.h> #define INF 2147483647 #define MIN INF+1 #define ll long long using namespace std; int N; vector<int> nodes[10005]; int visit[10005]; int max_depth = MIN; set<int> q; int father[10005]; int find(int n) { while(father[n] != n) { n = father[n]; } return n; } void _union(int a, int b) { int aa = find(a); int bb = find(b); father[aa] = father[bb]; } void dfs(int n, int depth) { // if(q.count(n)) { // return; // } bool isleaf = true; for(auto i:nodes[n]) { if(visit[i] == 0) { visit[i] = 1; dfs(i, depth + 1); visit[i] = 0; isleaf = false; } } if(isleaf) { if(depth > max_depth) { max_depth = depth; q.clear(); q.insert(n); } else if(depth == max_depth) { q.insert(n); } } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); cin >> N; for(int i = 0; i < N; i++) { visit[i] = 0; father[i] = i; } for(int i = 0; i < N - 1; i++) { int a, b; cin >> a >> b; a -= 1; b -= 1; nodes[a].push_back(b); nodes[b].push_back(a); _union(a,b); } set<int> s; for(int i = 0; i < N; i++) { if(i == father[i]) s.insert(father[i]); } if(s.size() > 1) { cout << "Error: " << s.size() << " components" << endl; return 0; } for(int i = 0; i < N; i++) { visit[i] = 1; dfs(i, 0); visit[i] = 0; } for(auto x:q) { cout << x + 1 << endl; // 下标开始位置不同罢了 } return 0; }超时代码:
#include<iostream> #include<string> #include<map> #include<vector> #include<set> #include<queue> #include<algorithm> #include<bits/stdc++.h> #define INF 2147483647 #define MIN INF+1 #define ll long long using namespace std; int N; vector<int> nodes[10005]; int visit[10005]; int max_depth = MIN; set<int> q; map<int, bool> has; int father[10005]; int find(int n) { while(father[n] != n) { n = father[n]; } return n; } void _union(int a, int b) { int aa = find(a); int bb = find(b); father[aa] = father[bb]; } void dfs(int n, int depth) { // if(q.count(n)) { // return; // } // if(has.find(n) != has.end()) // return; bool isleaf = true; for(auto i:nodes[n]) { if(visit[i] == 0) { visit[i] = 1; dfs(i, depth + 1); visit[i] = 0; isleaf = false; } } if(isleaf) { if(depth > max_depth) { max_depth = depth; // q.clear(); // q.insert(n); has.clear(); has[n] = true; } else if(depth == max_depth) { // q.insert(n); has[n] = true; } } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); cin >> N; for(int i = 0; i < N; i++) { visit[i] = 0; father[i] = i; } for(int i = 0; i < N - 1; i++) { int a, b; cin >> a >> b; a -= 1; b -= 1; nodes[a].push_back(b); nodes[b].push_back(a); _union(a,b); } set<int> s; for(int i = 0; i < N; i++) { if(i == father[i]) s.insert(father[i]); } if(s.size() > 1) { cout << "Error: " << s.size() << " components" << endl; return 0; } for(int i = 0; i < N; i++) { visit[i] = 1; dfs(i, 0); visit[i] = 0; } for(map<int,bool>::iterator i = has.begin(); i != has.end(); i++) { cout << i->first + 1 << endl; } return 0; }
#include<iostream> #include<string> #include<map> #include<vector> #include<set> #include<queue> #include<algorithm> #include<bits/stdc++.h> #define INF 2147483647 #define MIN INF+1 #define ll long long using namespace std; int N; vector<int> nodes[10005]; int visit[10005]; int max_depth = MIN; set<int> q; map<int, bool> has; int father[10005]; int find(int n) { while(father[n] != n) { n = father[n]; } return n; } void _union(int a, int b) { int aa = find(a); int bb = find(b); father[aa] = father[bb]; } void dfs(int n, int depth, int start) { // if(q.count(n)) { // return; // } // if(has.find(n) != has.end()) // return; bool isleaf = true; for(auto i:nodes[n]) { if(visit[i] == 0) { visit[i] = 1; dfs(i, depth + 1, start); visit[i] = 0; isleaf = false; } } if(isleaf) { if(depth > max_depth) { max_depth = depth; // q.clear(); // q.insert(n); has.clear(); has[start] = true; } else if(depth == max_depth) { // q.insert(n); has[start] = true; } } } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); cin >> N; for(int i = 0; i < N; i++) { visit[i] = 0; father[i] = i; } for(int i = 0; i < N - 1; i++) { int a, b; cin >> a >> b; a -= 1; b -= 1; nodes[a].push_back(b); nodes[b].push_back(a); _union(a,b); } set<int> s; for(int i = 0; i < N; i++) { if(i == father[i]) s.insert(father[i]); } if(s.size() > 1) { cout << "Error: " << s.size() << " components" << endl; return 0; } for(int i = 0; i < N; i++) { if(visit[i] == 0 && nodes[i].size() == 1) { visit[i] = 1; dfs(i, 0, i); visit[i] = 0; } } for(map<int,bool>::iterator i = has.begin(); i != has.end(); i++) { cout << i->first + 1 << endl; } return 0; }
#include <iostream> #include <vector> #include <algorithm> #include <unordered_set> #define dbg(x) cout << #x ": " << x << endl using namespace std; int N; vector<vector<int>> G; vector<vector<int>> deeps; vector<int> degrees; bool is_acyclic = true; unordered_set<int> visited; int dfs(int x, int from){ visited.insert(x); int n = G[x].size(); const vector<int>& g = G[x]; int max_deep = 0; for(int i = 0; i < n; i++){ if(visited.count(g[i]) == 0){ int deep; if(~deeps[x][i]){ deep = deeps[x][i]; } else{ deep = dfs(g[i], x); } if(deep > max_deep){ max_deep = deep; } deeps[x][i] = deep; } else if(g[i] != from){ // dbg(x); // dbg(from); // dbg(g[i]); is_acyclic = false; } } return max_deep + 1; } int main(){ // ios::sync_with_stdio(false); cin >> N; G.resize(N); // dbg(G.size()); deeps.resize(N); // dbg(deeps.size()); degrees.resize(N); // dbg(degrees.size()); for(int i = 0; i < N - 1; i++){ int p, q; cin >> p >> q; p--, q--; G[p].push_back(q); deeps[p].push_back(-1); G[q].push_back(p); deeps[q].push_back(-1); degrees[p]++; degrees[q]++; } // dbg("here"); vector<int> ans; int max_deep = 0, parts = 0; bool ok = true; for(int i = 0; i < N; i++){ // dbg("iter"); // dbg(i); if(visited.count(i) == 0){ dfs(i, -1); parts++; if((int)visited.size() != N || !is_acyclic){ // dbg(visited.size()); // dbg(is_acyclic); ok = false; } } if(i && ok){ break; } } for(int i = 0; i < N; i++){ if(true || degrees[i] <= 1){ visited.clear(); int deep = dfs(i, -1); if(deep > max_deep){ max_deep = deep; ans.clear(); ans.push_back(i); } else if(deep == max_deep){ ans.push_back(i); } } } if(!ok){ cout << "Error: " << parts << " components" << endl; } else{ sort(ans.begin(), ans.end()); for(auto x : ans){ cout << x + 1 << endl; } } }
//bfs宽度优先 #include<iostream> #include<cstdio> #include<queue> #include<map> #include<set> using namespace std; int main() { set<int> node_set; map<int, set<int> > edge_map; queue<int> node_queue; int count = 0;//树的数量 int pre[10001] = {0}; int pre2[10001] = {0}; int N = 0; cin>>N; for (int i = 0; i < N-1; i++) { int a,b; scanf("%d %d",&a,&b); // if (node_set.find(a) == node_set.end()) // node_set.insert(a); // if (node_set.find(b) == node_set.end()) // node_set.insert(b); node_set.insert(i+1); edge_map[a].insert(b); edge_map[b].insert(a); } node_set.insert(N); bool is_tree = true; int node_front; int level = -1; set<int> final_level; while (!node_set.empty()) { count ++; int node = *node_set.begin(); node_queue.push(node); node_queue.push(level); final_level.insert(node); while(!node_queue.empty()){ node_front = node_queue.front(); if (node_front < 0) { level --; node_queue.pop(); if (!node_queue.empty()){ final_level.clear(); node_queue.push(level); } continue; } final_level.insert(node_front); node_set.erase(node_front); set<int>::iterator iter = edge_map[node_front].begin(); for(; iter != edge_map[node_front].end();iter++){ if (*iter == pre[node_front]) continue; if (node_set.find(*iter) != node_set.end()) { if (pre[*iter] != 0) { is_tree = false; continue; } pre[*iter] = node_front; node_queue.push(*iter); } else is_tree = false; } node_queue.pop(); } } if (!is_tree){ cout<<"Error: "<<count<<" components"; } else { int level2 = -1; set<int> final2; node_front = *final_level.begin(); node_queue.push(node_front); node_queue.push(level2); while(!node_queue.empty()) { node_front = node_queue.front(); if (node_front < 0) { level2 --; node_queue.pop(); if (!node_queue.empty()){ final2.clear(); node_queue.push(level2); } continue; } final2.insert(node_front); set<int>::iterator iter = edge_map[node_front].begin(); for(; iter != edge_map[node_front].end();iter++){ if (*iter == pre2[node_front]) continue; pre2[*iter] = node_front; node_queue.push(*iter); } node_queue.pop(); } for (set<int>::iterator iiit = final2.begin(); iiit != final2.end(); iiit++) if (final_level.find(*iiit) == final_level.end()) final_level.insert(*iiit); for (set<int>::iterator it = final_level.begin(); it != final_level.end(); ){ cout<<*it; if (++it != final_level.end()) cout<<endl; } cout<<endl; } return 0; }
思路: 参考大佬 对于并查集推荐 https://blog.csdn.net/u013546077/article/details/64509038 #include <stdio.h> #include <iostream> #include <cstring> #include <algorithm> #include <set> #include <vector> #include <fstream> using namespace std; const int size = 10000; #ifndef debug ifstream ifile("case.txt"); //freopen ("case.txt","r",stdin); #define cin ifile #endif class DisjointSet { private: int *T, size, sum; int FindRoot(int i) { return T[i] < 0 ? i : (T[i] = FindRoot(T[i])); } public: DisjointSet(int _size) :size(_size) { T = new int[size]; Init(); } void Init() { sum = size; memset(T, -1, sizeof(int)*size); } bool Unioned(int i, int j) { return FindRoot(i) == FindRoot(j); } void Union(int i, int j)//合并领导层 { if ((i = FindRoot(i)) != (j = FindRoot(j)))// 不是连通的把一个领导层换掉 { T[i] = T[i] + T[j]; T[j] = i; sum--; }//如果是连通的就不用做任何事情 } int FindSum(int i)// 返回所有的节点的深度 { return -T[FindRoot(i)]; } int SumOfUnits()// 返回没有来连通的个数。 { return sum; } ~DisjointSet() { delete[] T; } }; vector<int> v[10000];// 这种存储方式是存储的孩子节点 int vis[10000]; void dfs(int i, int dist, int & Max) { vis[i] = dist; Max = max(Max, vis[i]); for (int k = 0; k < v[i].size(); k++) { if (vis[v[i][k]] == -1) { dfs(v[i][k], dist + 1, Max); } } } int main() { int i, j, temp; int n; cin >> n; DisjointSet ds(n); for (i = 0; i < n - 1; i++) { int a, b; cin >> a >> b; a--, b--; v[a].push_back(b); v[b].push_back(a); ds.Union(a, b);// 合并领导层这么说他们是连通的 } if (ds.SumOfUnits() == 1)// 全部是在一个连通图里面 { int start, Max; set<int> s; for (Max = start = i = 0; i < 2; i++)// 遍历两边就可以得到全部的最长的节点 { memset(vis, -1, sizeof(vis));// 因为要遍历两次所以清空一下。 dfs(start, 0, Max); for (j = 0; j < n; j++) { if (vis[j] == Max)// 记录层数量,如果是叶子层且节点最深那么就把她们记录下来 { s.insert(j); } } start = *s.begin();// 这个点可以任意取一个值 } for (set<int>::iterator it = s.begin(); it != s.end(); it++) { printf("%d\n", (*it) + 1); } } else// 如果不是一棵连通图那么就输出总共连通的单位 { printf("Error: %d components\n", ds.SumOfUnits()); } system("pause"); return 0; } -------------------------------------- 直接使用两个DFS即可 一个计算树高一个计算真正的最高的root。 计算最高的root 参考 别人的博客。 #include <iostream> #include <vector> #include <cstring> #include <cstdio> #include <set> using namespace std; const int maxn = 10010; vector<int> v[maxn]; bool visit[maxn]; int maxH = 0; vector<int> temp; vector<int> ans; set<int> s; void DFS(int x){ if(visit[x] == true){ return; } visit[x] = true; for(int i=0; i<v[x].size(); i++){ DFS(v[x][i]); } } void DFS1(int x,int height){ if(visit[x] == true){ return; } visit[x] = true; if(height > maxH){ temp.clear(); maxH = height; temp.push_back(x); }else if(maxH == height){ temp.push_back(x); } for(int i=0; i<v[x].size(); i++){ DFS1(v[x][i], height+1); } } int main(){ //freopen("case.txt","r",stdin); int N; scanf("%d",&N); int a,b; // 初始化连通集 //init(); for(int i=1; i<N; i++){ scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } memset(visit, false, sizeof(visit)); int count = 0; for(int i=1; i<= N; i++){ if(!visit[i]){ DFS(i); count++; } } if(count > 1){ printf("Error: %d components\n",count); return 0; }else{ memset(visit, false, sizeof(visit)); DFS1(1,1); memset(visit, false, sizeof(visit)); ans = temp; DFS1(ans[0],1); for(int i=0; i<temp.size(); i++){ s.insert(temp[i]); } for(int i=0; i<ans.size(); i++){ s.insert(ans[i]); } for(set<int>::iterator i=s.begin(); i != s.end(); i++){ /*if(i == s.begin()){ printf("%d",*i); }else{ printf(" %d",*i); }*/ printf("%d\n",*i); } } }
#include<cstring> #include<cstdio> #include<vector> #include<set> #include<iostream> using namespace std; const int maxn=10010; vector<int> G[maxn]; int N; int father[maxn]; bool vis[maxn]={false}; set<int> temp,ans; void init() { for(int i=1;i<=N;i++) { father[i]=i; vis[i]=false; } } int findFather(int x) { int a=x; while(x!=father[x]) x=father[x]; //father[a]=x while(a!=father[a]) { int z=a; a=father[a]; father[z]=x; } return x; } void Union(int u,int v) { int fau=findFather(u); int fav=findFather(v); if(fau!=fav) father[fau]=fav; } int maxHeight=0; void DFS(int root,int height) { vis[root]=1; if(height>maxHeight) { temp.clear(); temp.insert(root); maxHeight=height; } if(height==maxHeight) { temp.insert(root); } for(int i=0;i<G[root].size();i++) if(vis[G[root][i]]==false) DFS(G[root][i],height+1); } int main() { cin>>N; init(); for(int i=1;i<=N-1;i++) { int c1,c2; cin>>c1>>c2; G[c1].push_back(c2); G[c2].push_back(c1); Union(c1,c2); } int block=0; for(int i=1;i<=N;i++) { int fa=findFather(i); if(vis[fa]==false) { block++; vis[fa]=true; } } if(block!=1) cout<<"Error: "<<block<<" components"<<endl; else { memset(vis,0,sizeof(vis)); DFS(1,1); ans=temp; memset(vis,0,sizeof(vis)); DFS(*(ans.begin()),1); set<int>::iterator it; for(it=temp.begin();it!=temp.end();it++) ans.insert(*it); for(it=ans.begin();it!=ans.end();it++) cout<<*it<<endl; } }