树专题

1.建树
8 7
1 2
1 3
2 4
2 5
3 6
6 7
6 8

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a,b,n,m;
struct Node{
    int fa,lf,rg;
}node[5005];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        if(node[a].lf)
            node[a].rg=b;
        else
            node[a].lf=b;
        node[b].fa=a;
    }
    for(int i=1;i<=n;i++)
    {
        cout<<endl;
        cout<<i<<": ";
        if(node[i].lf) cout<<node[i].lf<<" ";
        if(node[i].rg) cout<<node[i].rg<<" ";
    }       
}

2.根结点到每个结点的距离
5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int fa[1005],rt,n;
struct Node{
    int da,flg,dis;
    int lf,rg;
}nod[1005];
void dfs(int u,int ds,int fd)//根节点到每个点的距离,在根节点的哪个方向 
{
    int vl=nod[u].lf,vr=nod[u].rg;
    if(vl==0 && vr==0)//叶子节点 
    {
        nod[u].dis=ds;return;
    }
    if(vl)//如果有左儿子 
    {
        if(fd==-1 || fd==0)
        {
            dfs(vl,ds+1,-1);nod[vl].flg=-1;
        }   
        if(fd==1)
        {
            dfs(vl,ds+1,1);nod[vl].flg=1;
        }
        nod[vl].dis=ds+1;
    }
    if(vr)//如果有右儿子 
    {
        if(fd==1 || fd==0)
        {
            dfs(vr,ds+1,1);nod[vr].flg=1;
        }
        if(fd==-1)
        {
            dfs(vr,ds+1,-1);nod[vr].flg=-1;
        }
        nod[vr].dis=ds+1;
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&nod[i].da,&nod[i].lf,&nod[i].rg);
        fa[nod[i].lf]=i,fa[nod[i].rg]=i;
    }
    for(int i=1;i<=n;i++)
        if(!fa[i]) {rt=i;break;}

    dfs(rt,0,0);
    for(int i=1;i<=n;i++)
        cout<<i<<","<<nod[i].dis<<","<<nod[i].flg<<endl;//每个节点到根节点的距离,是根节点的左儿子,还是右儿子 
}

3.树的重心

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=20000+100;
vector<int> G[maxn];
int t,n,vis[maxn],son[maxn],Size,ans;
void DFS(int u)
{
        son[u]=0;
        vis[u]=1;//已经使用过了,所以不找它的父亲了 
        int balance=0;//
        for(int i=0;i<G[u].size();i++)
        {
                int v=G[u][i];//所以不找它的父亲了  
                if(!vis[v]) 
                {
                    DFS(v);
                    son[u]+=son[v]+1;
                    balance=max(balance,son[v]+1);                  
                }
        }
//        cout<<u<<","<<son[u]<<","<<n - son[u] - 1<<endl;
        balance=max(balance,n - son[u] - 1);
        if(balance<Size||balance==Size&&u<ans)//子树同等大小下,结点要求最小
        {
                Size=balance;
                ans=u;
        }
}
int main()
{
        scanf("%d",&t);
        while(t--)
        {
                scanf("%d",&n);
                for(int i=1;i<=n;i++)//初始化
                {
                        vis[i]=0;
                        son[i]=0;
                        G[i].clear();
                }
                for(int i=0;i<n-1;i++)
                {
                       int x,y;
                       scanf("%d %d",&x,&y);
                       G[x].push_back(y);
                       G[y].push_back(x);
                }

                ans=n+2;
                Size=(1<<30);
                DFS(1);
                printf("%d %d\n",ans,Size);
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值