zoukankan      html  css  js  c++  java
  • 洛谷P2835 刻录光盘 题解 点的度数+并查集

    题目链接:https://www.luogu.com.cn/problem/P2835

    解题思路:

    如果A愿意借给B,则B的入度加一。

    然后计算一下有多少个点的入度为0,这些是我们需要分配光盘的。

    但是可能存在强联通分量,这种情况下,一个强联通分量里没有入读为0的点,但是我需要制定以下这个点。

    所以我用 并查集 来维护,如果A愿意借给B,则A、B属于同一个集合。

    首先计算有多少入度为0的点,假设有 (cnt_1) 个,找到这些点的同时将它们所属的集合标记为访问过。

    然后计算有多少个没有被标记过的集合,假设这个数量为 (cnt_2)

    则最终答案为: (cnt_1 + cnt_2)

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 220;
    int n, d[maxn], f[maxn], a, cnt;
    bool vis[maxn];
    void init() {
        for (int i = 1; i <= n; i ++) f[i] = i;
    }
    int Find(int x) {
        return x == f[x] ? x : f[x] = Find(f[x]);
    }
    void Union(int x, int y) {
        int a = Find(x), b = Find(y);
        f[a] = f[b] = f[x] = f[y] = min(a, b);
    }
    int main() {
        cin >> n;
        init();
        for (int i = 1; i <= n; i ++) {
            while ((cin >> a) && a) {
                d[a] ++;
                Union(i, a);
            }
        }
        for (int i = 1; i <= n; i ++) if (!d[i]) { vis[Find(i)] = true; cnt ++; }
        for (int i = 1; i <= n; i ++) if (!vis[Find(i)]) { vis[Find(i)] = true; cnt ++; }
        cout << cnt << endl;
        return 0;
    }
    
  • 相关阅读:
    HDU 4296 Buildings(贪心)
    HDU 4288 Coder(线段树)
    hdu 5073 Galaxy
    ZOJ 3905 Cake(贪心+dp)
    ZOJ 3903 Ant(公式推导)
    除法求逆元(扩展欧几里德和费马小定理)
    HDU 4442 Physical Examination(关于贪心排序)
    ACM vim配置
    2015 南阳ccpc The Battle of Chibi (uestc 1217)
    次小生成树(入门)
  • 原文地址:https://www.cnblogs.com/quanjun/p/12369058.html
Copyright © 2011-2022 走看看