Algoogle

Algorithm for Programming Contest

AOJ 2664 Shopping

Category: AOJ Tag: union-find

Shopping

問題概要


N個の材料がある.i番目の材料はx[i]円で買える.
幾つかの材料は魔法で別の材料にすることができる.AからBにできるならBからAにもできる.
必要な材料費の最小を求めよ.

解法


Union Fnidで関係をマージしてグループ中の最小額を採用すればいい.

コード


(2664.cpp) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <bits/stdc++.h>
using namespace std;
#define repi(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repi(i,0,n)

struct union_find
{
    vector<int> rnk, par;

    union_find() {}
    union_find(int n){
        rnk.assign(n,1);
        par.assign(n,0);
        for(int i = 0; i < n; i++) par[i] = i;
    }

    int find(int x) {
        if(x == par[x]) return x;
        else return par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        x = find(x); y = find(y);
        if(x == y) return;
        if(rnk[x] > rnk[y]) par[y] = x;
        else {
            par[x] = y;
            if(rnk[x] == rnk[y]) rnk[y]++;
        }
    }
    bool same(int x, int y) {
        x = find(x); y = find(y);
        return x == y;
    }
};

int n, m, x[5010];
union_find uf;
map<string, int> id;

int solve() {
    rep(i,n) x[uf.find(i)] = min(x[uf.find(i)], x[i]);
    int ans = 0;
    rep(i,n) ans += x[uf.find(i)];
    return ans;
}

void input() {
    cin >> n;
    string a, b; int y;
    rep(i,n) {
        cin >> a >> y;
        x[id[a] = i] = y;
    }
    uf = union_find(n);
    cin >> m;
    rep(i,m) {
        cin >> a >> b;
        uf.unite(id[a],id[b]);
    }
}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    cout << fixed << setprecision(12);
    input();
    cout << solve() << endl;
    return 0;
}

Comments