考查点:并查集求连通分量,DFS或BFS
思路:本题数据很弱,第一次直接用DFS就可以过,主要犯了啃爹的错误,在写循环遍历容器时for(int i=0;i<=s.size()-1;i++)是不对的,就是只能i<size()别取等号,本题高效率的方法是求连通分量时候用并查集,之后BFS和DFS都可以,但要用任意点所达到的最深处的点是根集合,这样只需两次DFS或BFS,当然不用直接暴力也是可以过的。注意后者可能会产生重复元素,这时要去重,直接输出处理或set都可以
暴力过的代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#define FOR(i, x, y) for(int i = x; i <= y; i++)
#define rFOR(i, x, y) for(int i = x; i >= y; i--)
#define MAXN 100010
#define oo 0x3f3f3f3f
using namespace std;
int n;
int vis[MAXN];
vector<int> G[MAXN];
int mlen;
void DFS(int index,int depth)
{
vis[index]=1;
if(depth>mlen){
mlen=depth;
}
for(int i=0;i<G[index].size();i++)
{
int u=G[index][i];
if(vis[u]==0){
DFS(u,depth+1);
}
}
}
int main()
{
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif // LOCAL
scanf("%d",&n);
vector<int> res;
FOR(i,1,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
int ans,cnt=0;
FOR(i,1,n)
{
if(!vis[i]){
DFS(i,1);
cnt++;
}
}
if(cnt!=1){
printf("Error: %d components",cnt);
}else{
cnt=0;
FOR(i,1,n)
{
memset(vis,0,sizeof(vis));
mlen=0;
DFS(i,1);
if(mlen>cnt){
res.clear();
cnt=mlen;ans=i;
res.push_back(i);
}else if(cnt==mlen){
res.push_back(i);
}
}
sort(res.begin(),res.end());
for(int i=0;i<res.size();i++)
{
printf("%d\n",res[i]);
}
}
return 0;
}
DFS版本:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#define FOR(i, x, y) for(int i = x; i <= y; i++)
#define rFOR(i, x, y) for(int i = x; i >= y; i--)
#define MAXN 100010
#define oo 0x3f3f3f3f
using namespace std;
int n;
vector<int> G[MAXN],temp,ans;
int mlen;
int fa[MAXN];
int isRoot[MAXN];
int findFather(int x)
{
int a=x;
while(x!=fa[x]){
x=fa[x];
}
while(a!=fa[a]){
int z=a;
a=fa[a];
fa[z]=x;
}
return x;
}
void Union(int a,int b)
{
int aa=findFather(a),bb=findFather(b);
if(aa!=bb){
fa[aa]=bb;
}
}
void init()
{
FOR(i,1,n)
fa[i]=i;
}
void DFS(int index,int depth,int pre)
{
if(depth>mlen){
temp.clear();
temp.push_back(index);
mlen=depth;
}else if(depth==mlen){
temp.push_back(index);
}
for(int i=0;i<G[index].size();i++)
{
int u=G[index][i];
if(u==pre) continue;
DFS(u,depth+1,index);
}
}
int main()
{
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif // LOCAL
scanf("%d",&n);
init();
FOR(i,1,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
Union(u,v);
}
set<int> res;
int cnt=0;
FOR(i,1,n)
{
isRoot[findFather(i)]=1;
}
FOR(i,1,n)
{
if(isRoot[i])cnt++;
}
if(cnt!=1){
printf("Error: %d components",cnt);
}else{
DFS(1,1,-1);
ans=temp;
DFS(ans[0],1,-1);
FOR(i,0,temp.size()-1)
{
ans.push_back(temp[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;
}
BFS版本:
注意图的BFS必须要标记数组标记是否入队,这里用dist数组既做到了标记,又完成了记录节点的距离,很巧
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define FOR(i,x,y) for(int i = x; i <= y; i++)
#define MAXN 10001
using namespace std;
int n;
vector<int> G[MAXN];
int mlen;
int fa[MAXN];
int isRoot[MAXN];
int dist[MAXN];
int findFather(int x)
{
int a=x;
while(x!=fa[x]){
x=fa[x];
}
while(a!=fa[a]){
int z=a;
a=fa[a];
fa[z]=x;
}
return x;
}
void Union(int a,int b)
{
int aa=findFather(a),bb=findFather(b);
if(aa!=bb){
fa[aa]=bb;
}
}
void init()
{
FOR(i,1,n)
fa[i]=i;
}
int BFS(int index)
{
memset(dist,-1,sizeof(dist));
int level=0;
queue<int> q;
q.push(index);
dist[index]=0;
int dmax=0;
while(!q.empty())
{
int cur=q.front();
q.pop();
int d=dist[cur];
for(int i=0;i<G[cur].size();i++){
int u=G[cur][i];
if(dist[u]==-1){
dist[u]=d+1;
q.push(u);
}
}
dmax=max(d,dmax);
}
return dmax;
}
int main()
{
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif // LOCAL
scanf("%d",&n);
init();
int u,v;
FOR(i,1,n-1)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
Union(u,v);
}
int cnt=0;
FOR(i,1,n)
{
if(fa[i]==i)cnt++;
}
if(cnt!=1){
printf("Error: %d components",cnt);
}else{
set<int> ans,tot;
int d=BFS(1);
FOR(i,1,n)
{
if(dist[i]==d) ans.insert(i);
}
d=BFS(*ans.begin());
FOR(i,1,n)
{
if(dist[i]==d) ans.insert(i);
}
for(set<int>::iterator it=ans.begin();it!=ans.end();it++){
printf("%d\n",*it);
}
}
return 0;
}