A1021 Deepest Root (25分)

运行超时的代码以及算法优化的代码

:运行超时:

#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
using namespace std;
//A1021
const int maxn=10010;
int n;
set<int> roots;
vector<int> graph[maxn];
bool visit[maxn]={false};
int Maxdepth=-1;

void DFS(int root,int index,int layer){
	visit[index]=true;
	if(layer>Maxdepth){
		//清空set数组 
		roots.clear();
		roots.insert(root);
		Maxdepth=layer;
	}else if(layer==Maxdepth){
		roots.insert(root);
	}
	for(int i=0;i<graph[index].size();i++){
		int next=graph[index][i];
		if(visit[next]==false){
			//没被访问过
			DFS(root,next,layer+1); 
		}
	}
}
int DFStrave(){
	int num=0;
	for(int i=1;i<=n;i++){
		if(visit[i]==false){
			DFS(i,i,0);//开始节点的深度为0 
			num++;//计算几个连通分量 			
		}
	}
	return num;//又不记得返回! 
}
int main()
{
	scanf("%d",&n);
	int a,b;
	//n个节点输入n-1条边:如果联通必定是一棵树 
	for(int i=1;i<=n-1;i++){
		scanf("%d %d",&a,&b);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	//先判断是否是树:1.无环 2.联通 (无需判断是否有环) 
	int connectNum=DFStrave();
	if(connectNum>1){
		printf("Error: %d components",connectNum);
	}else{
		//对每一个节点看最大的Maxdepth		 
		 for(int i=1;i<=n;i++){
		 	//初始化visit数组
			memset(visit,false,sizeof(visit)); 
		 	DFS(i,i,0);		
		 }
		 set<int> ::iterator it;
		 for(it=roots.begin();it!=roots.end();it++){
		 	printf("%d\n",*it);
		 }
	} 
	
return 0;
	}

:优化策略:在连通个数不是1的时候只要深度遍历两次即可

先从⼀个结点dfs后保留最⾼⾼度拥有的结点们,然后从这些结点中的其中任意⼀个开始dfs得到最⾼⾼度的结点们,这两个结点集合的并集就是所求。

这点在算法笔记的344页有证明:有点长,可以记住结论直接用

#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
using namespace std;
//A1021
const int maxn=10010;
int n;
set<int> roots,ans;
vector<int> graph[maxn];
bool visit[maxn]={false};
int Maxdepth=-1;

void DFS(int root,int index,int layer){
	visit[index]=true;
	if(layer>Maxdepth){
		//清空set数组 
		roots.clear();
		roots.insert(index);//这时候保存的就是深度遍历一次到达最深的节点的集合 
		Maxdepth=layer;
	}else if(layer==Maxdepth){
//		cout<<"insert"<<index<<endl;
		roots.insert(index);
	}
	for(int i=0;i<graph[index].size();i++){
		int next=graph[index][i];
		if(visit[next]==false){
			//没被访问过
			DFS(root,next,layer+1); 
		}
	}
}
int DFStrave(){
	int num=0;
	for(int i=1;i<=n;i++){
		if(visit[i]==false){
			DFS(i,i,0);//开始节点的深度为0 
			num++;//计算几个连通分量 			
		}
	}
	return num;//又不记得返回! 
}
int main()
{
	scanf("%d",&n);
	int a,b;
	//n个节点输入n-1条边:如果联通必定是一棵树 
	for(int i=1;i<=n-1;i++){
		scanf("%d %d",&a,&b);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}
	//先判断是否是树:1.无环 2.联通 (无需判断是否有环) 
	int connectNum=DFStrave();
	if(connectNum>1){
		printf("Error: %d components",connectNum);
	}else{
	
		DFS(1,1,0);
		memset(visit,false,sizeof(visit)); 

//		cout<<"maxdepth="<<Maxdepth<<endl;
		set<int> ::iterator temp;
		temp=roots.begin();
		ans=roots;//可以直接赋值 
		DFS(*temp,*temp,0);
		
		set<int> ::iterator it;
		for(it=ans.begin();it!=ans.end();it++){
			roots.insert(*it);
			//将第一个dfs的节点insert到最终的set里(set可自动完成去重和排序) 
		}		 
		 for(it=roots.begin();it!=roots.end();it++){
		 	printf("%d\n",*it);
		 }
	} 
	
return 0;
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值