POJ1655树的重心 问删除哪个点,使余下的各个子树结点个数的最大值最小.

本文详细介绍了使用C语言实现深度优先搜索算法来遍历图的过程,包括图的构建、DFS函数的实现以及如何通过DFS找到图中所有节点的连通情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #define Max(a,b) (a>b?a:b)  
    #define Min(a,b) (a<b?a:b)  
    #define  nMax 20010  
      
    struct Edge{  
        int v;  
        int next;  
    }edge[2 * nMax];//保存双向图  
    int preEdge[nMax];//同一个起点的上一条边  
    int n;  
    bool flag[nMax];  
    int childNum[nMax];//每个节点下的节点总数  
    int min;  
    int childMax[nMax];//每个节点去掉后其他子树最多点数  
      
    int dfs(int root)  
    {  
        flag[root] = true;  
        int p = preEdge[root];//以root为起点的边的标示也就是edge的下标  
      
        while (p)  
        {  
            int v = edge[p].v;//root连接的点  
            if (!flag[v])  
            {  
                childNum[root] += dfs(v);//求root点下的所有节点  
                childMax[root] = Max(childNum[edge[p].v], childMax[root]);//求root点下孩子节点中的最大值  
            }  
            p = edge[p].next;//以root为起点的上一条边  
        }  
        childMax[root] = Max(n - childNum[root], childMax[root]);//root下孩子节点中的最大值和祖先节点总数的最大值作为本节点的最大值  
        return childNum[root];//返回本节点的总数  
    }  
      
    int  main()  
    {  
        int t;  
        int u, v;  
        while (scanf("%d", &t) != EOF)  
        {  
            while (t --)  
            {  
                memset(preEdge, 0, sizeof(preEdge));  
                memset(flag, false, sizeof(flag));  
                min = 0x0FFFFFFF;  
                scanf("%d", &n);  
                for (int i = 1; i < 2 * (n - 1); i += 2)//建图  
                {  
                    scanf("%d %d", &u, &v);  
                    edge[i].v = v;  
                    edge[i].next = preEdge[u];  
                    preEdge[u] = i;  
      
                    edge[i + 1].v = u;  
                    edge[i + 1].next = preEdge[v];  
                    preEdge[v] = i + 1;  
                }  
                if (n == 1)  
                {  
                    printf("1 0\n");  
                    continue;  
                }  
                //memset(childNum, 0, sizeof(childNum));  
                for (int i = 1; i <= n; ++ i)  
                {  
                    childNum[i] = 1;  
                    childMax[i] = -1;  
                }  
                dfs(1);//dfs  
                int mMin = 0x0FFFFFFF, k;  
                for (int i = 1; i <= n; ++ i)//求最小值  
                {  
                    if (mMin > childMax[i])  
                    {  
                        k = i;  
                        mMin = childMax[i];  
                    }  
                }  
                printf("%d %d\n", k, mMin);  
            }  
        }  
        return 0;  
    }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值