zoukankan      html  css  js  c++  java
  • poj2378

    题意:给一棵n个节点的无根树,问去掉那一点可以使各连通分支中的节点数均<=n/2。

    分析:任意选定一个根,用自底向上的方法记录每棵子树的节点数。这样对于每个节点就可以通过它子树的节点数量迅速地判断它是否符合条件,别忘了还要判断它上面那个它祖宗所在的连通分支(节点数为n减去其各个子树的连通分支数再减1)。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define maxn 10005
    
    struct Edge
    {
        int v, next;
    } edge[maxn * 2];
    
    struct Point
    {
        int id, degree;
    } point[maxn];
    ;
    
    int n, ncount;
    int layer[maxn];
    int head[maxn];
    bool vis[maxn];
    int q[maxn];
    int num[maxn];
    bool ans[maxn];
    
    bool operator <(const Point &a, const Point &b)
    {
        return a.degree > b.degree;
    }
    
    void addedge(int a, int b)
    {
        edge[ncount].v = b;
        edge[ncount].next = head[a];
        head[a] = ncount++;
    }
    
    void input()
    {
        scanf("%d", &n);
        memset(head, -1, sizeof(head));
        for (int i = 0; i < n - 1; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            a--;
            b--;
            addedge(a, b);
            addedge(b, a);
        }
    }
    
    void bfs()
    {
        int front = 0, rear = 0;
        memset(vis, 0, sizeof(vis));
        q[rear++] = 0;
        vis[0] = true;
        layer[0] = 0;
        while (front != rear)
        {
            int u = q[front++];
            for (int i = head[u]; ~i; i = edge[i].next)
            {
                int v = edge[i].v;
                if (vis[v])
                    continue;
                q[rear++] = v;
                layer[v] = layer[u] + 1;
                vis[v] = true;
            }
        }
    }
    
    void make()
    {
        for (int i = 0; i < n; i++)
        {
            point[i].id = i;
            point[i].degree = layer[i];
        }
    }
    
    void work()
    {
        memset(ans, 0, sizeof(ans));
        for (int i = 0; i < n; i++)
        {
            int u = point[i].id;
            bool ok = true;
            num[u] = 1;
            for (int j = head[u]; ~j; j = edge[j].next)
            {
                int v = edge[j].v;
                if (layer[v] >= layer[u])
                {
                    num[u] += num[v];
                    if (num[v] > n / 2)
                        ok = false;
                }
            }
            if (n - num[u] > n / 2)
                ok = false;
            ans[u] = ok;
        }
        for (int i = 0; i < n; i++)
            if (ans[i])
                printf("%d\n", i + 1);
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        input();
        bfs();
        make();
        sort(point, point + n);
        work();
        return 0;
    }
  • 相关阅读:
    三种常用排序理论
    无参带返回类型方法练习
    无参带返回类型方法总结
    Java_无参数无返回类型方法及练习
    Java_方法的调用②及案例
    方法内存分析(进栈(压栈)、出栈(弹栈))
    Java_方法的基本语法格式
    Java_方法的调用①及案例
    Java_方法的定义以及分类
    Java_break与continue区别
  • 原文地址:https://www.cnblogs.com/rainydays/p/2582376.html
Copyright © 2011-2022 走看看