运行超时的代码以及算法优化的代码
:运行超时:
#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;
}