题目大意:给定一个图,判断是不是一棵包含全部顶点的树。如果是,找出所有的顶点按顺序输出,满足的条件为以该顶点为根的树拥有最大的深度;否则输出有几个连通块。
解题思路:用 vector 存储图,dfs 进行图的遍历搜索,可以获得最大深度;是否存在环 ( n 个点 n-1 条边,如果不是树,必是环(我的理解)),不存在环的条件可以用某点 dfs 除其父节点外其他相邻点均未被访问来判断。具体看代码细节(注:需要进行必要的剪枝操作,不然有一组样例会超时;除了剪枝,也可以利用 PAT 的一个小BUG,超时的那组对数据的敏感性不高,只要度为 1 都是结果,可以做个 n>1000 的判断,省去一些时间,不过这是投机取巧罢了,代码就不上了)。
剪枝操作也是险过。。。
题目链接:https://www.patest.cn/contests/pat-a-practise/1021
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
vector<int > VV[10005];
bool visited[10005];
bool haveRing = false;//是否有回路标记
int MaxL;//在单一的dfs中最大
int MaxiumL = -1;//全局最大
void dfs(int s,int level)
{
visited[s] = true;
MaxL = max(MaxL,level);
int flag = 0;
for(vector<int>::iterator it=VV[s].begin();it!=VV[s].end();++it)
{
if(visited[*it] == false)
dfs(*it,level+1);
else
++flag;
}
if(flag >= 2)//除父节点外有其他相邻节点被访问
haveRing = true;
}
int main(int argc, char** argv) {
int n;
cin >> n;
for(int i=0;i<n-1;++i)
{
int tmp1,tmp2;
cin >> tmp1 >> tmp2;
VV[tmp1].push_back(tmp2);
VV[tmp2].push_back(tmp1);
}
for(int i=1;i<=n;++i)
{
MaxL = -1;//每个循环初始化
fill(visited,visited+n+1,false);
dfs(i,1);
MaxiumL = max(MaxiumL,MaxL);
}
if(haveRing == false)
{
for(int i=1;i<=n;++i)
{
if(VV[i].size() <= 1)//剪枝。如果存在,则其度必小于等于1
{
MaxL = -1;
fill(visited,visited+n+1,false);
dfs(i,1);
if(MaxL == MaxiumL)
cout<< i << endl;
}
}
}
else
{
int cnt = 0;
fill(visited,visited+n+1,false);
for(int i=1;i<=n;++i)
{
if(visited[i] == false)
{
++cnt;//连通块计数
dfs(i,1);
}
}
cout<< "Error: " << cnt << " components";
}
return 0;
}