Skip to content

14189: 【原4189】西部世界

题目

题目描述

author: DS TA 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4189

Description

西部世界中有$N$个小镇, 小镇编号为1至$N$, 可以把西部世界的地图看成是一棵树, $N-1$条双向道路连接$N$个小镇, 满足任意两个小镇可以互相到达. 机器人中的领袖Dolores Abernathy觉醒了, 她打算揭竿起义,反抗人类. Dolores计划攻占一个小镇, 攻占某个小镇$u$后可以视为 去掉所有连接$u$的道路, 则剩下的$N-1$个小镇将分成若干个连通块, 为了让这场战役走向胜利, 她认为连通块规模最大的小镇数目应小于等于$N/2$. 身为觉醒机器人中的西部牛仔, 你来告诉她可以攻占的小镇有哪些.

Input Format

第一行包含一个正整数$N$,表示小镇的个数. 接下来$N-1$行,每行两个整数$u$, $v$表示一条道路 连接小镇$u$和小镇$v$.

Output Format

输出若干行,每行一个整数,表示可以攻占的小镇, 要求以升序顺序输出.

Sample Input

8 1 2 1 3 2 4 2 5 3 6 3 7 4 8

Sample Output

1 2

ligongzzz's solution

#include <iostream>
#include <vector>
using namespace std;

class node {
public:
    int parent = 0, child_num = 0;
    vector<int> child;
};

vector<node> tree_data;

int dfs(int root) {
    tree_data[root].child_num = 1;
    for (auto p : tree_data[root].child) {
        if (p != tree_data[root].parent) {
            tree_data[p].parent = root;
            tree_data[root].child_num += dfs(p);
        }
    }
    return tree_data[root].child_num;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;

    tree_data.resize(n + 1);

    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        tree_data[u].child.push_back(v);
        tree_data[v].child.push_back(u);
    }

    dfs(1);

    for (int i = 1; i <= n; ++i) {
        if (n - tree_data[i].child_num > n / 2) {
            continue;
        }
        bool flag = true;
        for (auto p : tree_data[i].child) {
            if (p != tree_data[i].parent) {
                if (tree_data[p].child_num > n / 2) {
                    flag = false;
                    break;
                }
            }
        }
        if (flag) {
            cout << i << " ";
        }
    }

    return 0;
}

Neight99's solution

#include <iostream>

using namespace std;

const int maxN = 1e5 + 100;

struct Node {
    int data;
    Node *next;

    Node(int d = 0, Node *n = 0) : data(d), next(n) {}
};

Node son[maxN] = {0};
int father[maxN] = {0}, Size[maxN] = {0}, ans[maxN] = {};
bool isNode[maxN] = {0};

int DFS(int, int);

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int N, k = 0, root;
    cin >> N;
    for (int i = 1; i < N; i++) {
        int u, v;
        cin >> u >> v;
        son[u].data = u;
        son[v].data = v;
        ans[u] = ans[v] = 1;
        if ((!isNode[u] && !isNode[v]) || (isNode[u] && !isNode[v])) {
            Node *p = &(son[u]);
            while (p->next != NULL) {
                p = p->next;
            }
            p->next = new Node(v);
            father[v] = u;
            isNode[u] = isNode[v] = 1;
        } else if (isNode[v] && isNode[u]) {
            Node *p = &son[v];
            while (p->next != NULL) {
                p = p->next;
            }
            p->next = new Node(u);
            father[u] = v;
            isNode[u] = isNode[v] = 1;
        }
    }

    for (int i = 1; i <= N; i++) {
        if (father[i] == 0) {
            root = i;
            break;
        }
    }

    DFS(root, N);

    for (int i = 1; i <= N; i++) {
        bool flag = 1;
        Node *p = &son[i];
        while (p->next != NULL) {
            p = p->next;
            if (Size[p->data] > N / 2) {
                flag = 0;
                break;
            }
        }
        if (N - Size[i] - 1 > N / 2) {
            flag = 0;
        }
        if (flag) {
            ans[k] = i;
            k++;
        }
    }

    for (int i = 0; i < k; i++) {
        cout << ans[i] << '\n';
    }

    return 0;
}

int DFS(int x, int N) {
    if (son[x].next == NULL) {
        return 1;
    } else {
        Node *p = &(son[x]);
        while (p->next != NULL) {
            p = p->next;
            Size[x] += DFS(p->data, N);
        }
        return Size[x] + 1;
    }
}

q4x3's solution

/**
 * dfs
 * 不能用vector真是太烦了
 * TAT
 **/
#include <iostream>

using namespace std;

int map[100233][100], sonnum[100233];
int N, tmp1, tmp2, siz[100233], vis[100233];

int dfs(int rt) {
    siz[rt] = 1;
    vis[rt] = 1;
    for(int i = 1;i <= sonnum[rt];++ i) {
        if(! vis[map[rt][i]]) {
            siz[rt] += dfs(map[rt][i]);
        }
    }
    return siz[rt];
}

bool check(int num) {
    if(N - siz[num] > (N >> 1)) return 0;
    for(int i = 1;i <= sonnum[num];++ i) {
        if(siz[map[num][i]] < siz[num] && siz[map[num][i]] > (N >> 1)) return 0;
    }
    return 1;
}

int main() {
    scanf("%d", &N);
    for(int i = 0;i < N - 1;++ i) {
        scanf("%d%d", &tmp1, &tmp2);
        map[tmp1][++ sonnum[tmp1]] = tmp2;
        map[tmp2][++ sonnum[tmp2]] = tmp1;
    }
    dfs(1);
    for(int i = 1;i <= N;++ i) {
        if(check(i)) printf("%d ", i);
    }
    printf("\n");
    return 0;
}

victrid's solution

#include <cstdio>
#include <iostream>
using namespace std;
struct ln {
    int pos;
    ln* next;
};

ln lis[1000005];
int sz[1000005]     = {0};
int parent[1000005] = {0};

int DFS(int pos) {
    sz[pos] = 1;
    ln* nx  = &lis[pos];
    while (nx->next != NULL) {
        nx = nx->next;
        if (parent[pos] != nx->pos) {
            parent[nx->pos] = pos;
            sz[pos] += DFS(nx->pos);
        }
    }
    return sz[pos];
}

int main() {
    int N, p, q;
    scanf("%d", &N);
    for (int i = 1; i < N; i++) {
        scanf("%d%d", &p, &q);
        lis[p].pos = p;
        lis[q].pos = q;
        ln* pp     = &lis[p];
        while (pp->next != nullptr) {
            pp = pp->next;
        }
        pp->next = new ln{q, nullptr};
        ln* qp   = &lis[q];
        while (qp->next != nullptr) {
            qp = qp->next;
        }
        qp->next = new ln{p, nullptr};
    }
    DFS(1);
    //Only one needed. I'm blind.
    for (int i = 1; i <= N; ++i) {
        if (N - sz[i] > N / 2) {
            continue;
        }
        bool flag = true;
        ln* nx    = &lis[i];
        while (nx->next != NULL) {
            nx = nx->next;
            if (parent[i] != nx->pos) {
                if (sz[nx->pos] > N / 2) {
                    flag = false;
                    break;
                }
            }
        }
        if (flag) {
            printf("%d ", i);
        }
    }
    return 0;
}