Hedwig's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: test/weighted_unionfind.test.cpp

Depends on

Code

#include <bits/stdc++.h>
using namespace std;

#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1330"
#include "../data_structures/weighted_unionfind.cpp"

void solve(int n, int m) {
    WeightedUnionFind<int, 0> wuf(n);
    int a, b, w;
    for (int i = 0; i < m; i++) {
        char q;
        cin >> q;
        if (q == '!') {
            cin >> a >> b >> w;
            wuf.unite(--a, --b, w);
        } else {
            cin >> a >> b;
            if (!wuf.same(--a, --b))
                cout << "UNKNOWN\n";
            else
                cout << wuf.diff(a, b) << '\n';
        }
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    int n, m;
    while (1) {
        cin >> n >> m;
        if (n == 0 && m == 0) break;
        solve(n, m);
    }

    return 0;
}
#line 1 "test/weighted_unionfind.test.cpp"
#include <bits/stdc++.h>
using namespace std;

#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1330"
#line 3 "data_structures/weighted_unionfind.cpp"
using namespace std;

// WeightedUnionFind
// 通常のUnionFindに加えて, 同じグループにいるノードの親に対する重みも
// 管理するデータ構造.
template <typename Abel, Abel unit>
struct WeightedUnionFind {
    int n;
    vector<int> parents;
    vector<Abel> diff_weight;

    WeightedUnionFind(int n) : n(n) {
        parents.assign(n, -1);
        diff_weight.assign(n, unit);
    }

    // find
    // xの親を返す. 経路圧縮するため, diff_weightも更新する
    // 制約: 0 <= x < n
    int find(int x) {
        if (parents[x] < 0)
            return x;
        else {
            int p = find(parents[x]);
            diff_weight[x] += diff_weight[parents[x]];
            return parents[x] = p;
        }
    }

    // weight
    // xのparentからの重みを返す
    // 制約: 0 <= x < n
    Abel weight(int x) {
        find(x);
        return diff_weight[x];
    }

    // diff
    // xとyが同じグループにいる時, xに対するyの重みを返す.
    // xとyが同じグループにいない時, 返す値には意味がない.
    // 制約: 0 <= x,y < n, xとyは同じグループ
    Abel diff(int x, int y) {
        return weight(y) - weight(x);
    }

    // unite
    // weight(y) = weight(x) + wとなるようにxとyを併合する.
    // もしすでにxとyが同じグループでweight(y) != weight(x) + wであればfalseを返す.
    // そうでない場合はtrueを返す.
    // 制約: 0 <= x,y < n
    bool unite(int x, int y, Abel w) {
        w += weight(x);
        w -= weight(y);

        x = find(x);
        y = find(y);
        if (x == y) {
            if (diff(x, y) == w)
                return true;
            else
                return false;
        }

        if (parents[x] > parents[y]) {
            swap(x, y);
            w *= -1;
        }

        parents[x] += parents[y];
        parents[y]     = x;
        diff_weight[y] = w;
        return true;
    }

    // same
    // xとyが同じかどうか判定する
    // 制約: 0 <= x,y < n
    bool same(int x, int y) {
        return find(x) == find(y);
    }

    // size
    // xと同じグループのサイズを返す.
    // 制約: 0 <= x < n
    int size(int x) {
        return -parents[find(x)];
    }
};
#line 6 "test/weighted_unionfind.test.cpp"

void solve(int n, int m) {
    WeightedUnionFind<int, 0> wuf(n);
    int a, b, w;
    for (int i = 0; i < m; i++) {
        char q;
        cin >> q;
        if (q == '!') {
            cin >> a >> b >> w;
            wuf.unite(--a, --b, w);
        } else {
            cin >> a >> b;
            if (!wuf.same(--a, --b))
                cout << "UNKNOWN\n";
            else
                cout << wuf.diff(a, b) << '\n';
        }
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    int n, m;
    while (1) {
        cin >> n >> m;
        if (n == 0 && m == 0) break;
        solve(n, m);
    }

    return 0;
}
Back to top page