21.

dfs和求连通分量。可以用并查集统计连通分量个数。对每一个结点dfs,求出以它作为结点的树的高度。vector真是非常好用的东西,用来存稀疏图再好不过,一开始用数组和动态分配都会内存溢出,用vector一下子就解决。然后就是dfs要注意进栈出栈。

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int *set,N,stack[10001],sp=-1,maxpath=-1;
bool *visit;
vector<int>root;
vector<vector<int>>G;

int Find(int n)
{
    if(set[n]<0)return n;
    else return Find(set[n]);
}

void UnionBySize(int n1,int n2)
{
    int r1=Find(n1),r2=Find(n2);
    if(r1==r2)return ;
    if(set[r1]<=set[r2])
    {
        set[r1]+=set[r2];
        set[r2]=r1;
    }
    else
    {
        set[r2]+=set[r1];
        set[r1]=r2;
    }
    return ;
}

void dfs(int S,int u)
{
    stack[++sp]=u;
    visit[u]=true;
    if(sp+1>maxpath)
    {
        maxpath=sp+1;
        root.clear();
        root.push_back(S);
        set[S]=0;
    }
    else if(sp+1==maxpath)
    {
        if(set[S]!=0)root.push_back(S);
        set[S]=0;
    }
    for(vector<int>::iterator v=G[u].begin();v!=G[u].end();v++)
    {
        if(visit[*v]==false)
            dfs(S,*v);
    }
    sp--;
    return ;

}

int main()
{
    cin>>N;
    G.resize(N+1);

    set=new int[N+1];
    fill(set,set+N+1,-1);

    visit=new bool[N+1];
    fill(visit,visit+N+1,false);

    for(int i=1;i<=N-1;i++)
    {
        int n1,n2;
        cin>>n1>>n2;
        G[n1].push_back(n2);
        G[n2].push_back(n1);
        UnionBySize(n1,n2);
    }

    for(int i=1,cnt=0;i<=N;i++)
    {
        if(set[i]<0)cnt++;
        if(i==N&&cnt>1)
        {
            cout<<"Error: "<<cnt<<" components";
            return 0;
        }
    }

    for(int u=1;u<=N;u++)
    {
        fill(visit,visit+N+1,false);
        dfs(u,u);
    }
    for(vector<int>::iterator p=root.begin();p!=root.end();p++)
    {
        cout<<*p<<endl;
    }
}
原文地址:https://www.cnblogs.com/KRCheung/p/6599267.html