Problem:
C : Shopping / 買い物
問題文
料理が得意な2D君は昼ごはんを作ろうとしている。料理には
N
個の材料
a_{0}, a_{1}, … , a_{N−1}
が全てが必要である。
さて、今2D君の家の冷蔵庫には一つも材料が入っていないので、スーパーに買いに行かなければならない。スーパーでは材料
a_{i}
を値段
x_{i}
円で買うことができる。
2D君は魔法使いでもあり、
M
種類の魔法が使える。
i
番目の魔法を材料
s_{i}
にかければ材料
t_{i}
に、また逆に
t_{i}
にかければ
s_{i}
に変えることができる。さらに、一つの材料に対して複数の魔法を繰り返して使うことができる。例えば、
p
から
q
に変える魔法と、
q
から
r
に変える魔法の2つを使って、
p
から
r
を得ることができる。
2D君は魔法の力を借りてなるべく安く材料を揃えることにした。料理を完成させるために2D君が買う必要のある材料の、値段の総和の最小値を求めよ。
入力
入力は以下の形式で与えられる。
N
a_{0}
x_{0}
…
a_{N−1}
x_{N−1}
M
s_{0}
t_{0}
…
s_{M−1}
t_{M−1}
制約
数値はすべて整数である
材料の名前はすべて
1
文字以上
10
文字以下のアルファベット小文字からなる
i ≠ j
なら
a_{i} ≠ a_{j}
1 \≤ x_{i} \≤ 1,000
1 \≤ N \≤ 5,000
0 \≤ M \≤ {\rm min}(N(N−1)
/
2, 1000)
s_{i} ≠ t_{i}
s_{i},t_{i}
の組に重複はない
s_{i},t_{i}
は
a_{0},…,a_{N−1}
に含まれる
出力
答えを1行で出力せよ。
サンプル
サンプル入力1
2
tako 2
yaki 1
1
tako yaki
魔法によって安い yaki を tako に変えることができるので、 yaki を
2
個買えばよい。
サンプル出力1
2
サンプル入力2
5
a 1
b 2
c 2
d 4
e 3
5
b a
a c
c d
e b
c b
サンプル出力2
5
下に示すように、全ての材料を a から変えてそろえることができる。
a : a そのまま
b : a -> c -> b
c : a -> c
d : a -> c -> d
e : a -> b -> e

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define rep(i,s,n) for (int i = (int)(s); i < (int)(n); i++)
#define all(v) (v).begin(),(v).end()
using namespace std;
using ll = long long;

template<typename T>
bool chmin(T &a, const T &b){
    if (a <= b) return false;
    a = b;
    return true;
}


template<typename T>
bool chmax(T &a, const T &b){
    if (a >= b) return false;
    a = b;
    return true;
}

int main(){
    cin.tie(0)->sync_with_stdio(0);

    int n; cin >> n;
    map<string,ll> nedan;
    vector<string> trs;

    rep(i,0,n){
        string s; cin >> s;
        ll x; cin >> x;
        nedan[s] = x;
        trs.push_back(s);
    }

    set<string> seen;
    map<string,string> taio;
    map<string,vector<string>> ikeru;

    int m; cin >> m;
    rep(i,0,m){
        string s, t; cin >> s >> t;
        ikeru[s].push_back(t);
        ikeru[t].push_back(s);
    }

    int piv = 0;
    rep(st,0,n){
        if(seen.find(trs[st]) != seen.end())continue;
        vector<string> mada;
        seen.insert(trs[st]);
        mada.push_back(trs[st]);
        while(!mada.empty()){
            string s = mada.back();
            mada.pop_back();
            taio[s]=trs[st];
            chmin(nedan[trs[st]],nedan[s]);
            for (string t: ikeru[s]){
                if(seen.find(t)==seen.end()){
                    seen.insert(t);
                    mada.push_back(t);
                }
            }
        }
    }

    ll ans = 0;
    rep(i,0,n){
        ans += nedan[taio[trs[i]]];
    }
    cout << ans << '\n';

}
accuracy: 1
time_ms: 10
memory_kb: 5292
final_rank: 15

code_snippet: #include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;

map<string,int> ms1;
map<string,string> ms2;
map<string,int> ms3;
vector<string> vec;

string f2(string s){
	if(ms2[s]==s){
		return s;
	}else{
		ms2[s]=f2(ms2[s]);
		return ms2[s];
	}
}

int main() {
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		string s;
		int n;
		cin>>s>>n;
		vec.push_back(s);
		ms2[s]=s;
		ms1[s]=n;
		ms3[s]=n;
	}
	int q;
	cin>>q;
	for(int i=0;i<q;i++){
		string s1,s2;
		cin>>s1>>s2;
		s1=f2(s1);
		s2=f2(s2);
		if(s1!=s2){
			int n1=ms1[s1];
			int n2=ms1[s2];
			if(n1<n2){
				ms2[s2]=s1;
				ms1[s1]=n1;
			}else{
				ms2[s1]=s2;
				ms1[s2]=n2;
			}
		}
	}
	int ans=0;
	for(int i=0;i<vec.size();i++){
		ans+=ms1[f2(vec[i])];
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4448
final_rank: 9

code_snippet: #include<bits//stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define req(i,n) for(int i = 1;i <=  n; i++)
#define rrep(i,n) for(ll i = n-1;i >= 0;i--)
#define ALL(obj) begin(obj), end(obj)
#define RALL(a) rbegin(a),rend(a)
typedef long long int ll;
typedef long double ld;
const int MAX = 510000;
const ll MOD = 1000000007;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
const ll INF = 1e18;
struct UnionFind {
    vector<int> par;
    UnionFind(int n) : par(n, -1) { }
    void init(int n) { par.assign(n, -1); }
    int root(int x) {
        if (par[x] < 0) return x;
        else return par[x] = root(par[x]);
    }
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    bool unite(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (par[x] > par[y]) swap(x, y); // merge technique
        par[x] += par[y];
        par[y] = x;
        return true;
    }
    int size(int x) {
        return -par[root(x)];
    }
};
int main(){
    int n,m;cin >>n;string s,t;
    vector<int> a(n);map<string,int> mp;
    rep(i,n){
        cin >> s>>a[i];
        mp[s]=i;
    }UnionFind uf(n+2);cin >>m;
    rep(i,m){
        cin >>s>>t;
        uf.unite(mp[s],mp[t]);
    }rep(i,n){
        rep(j,n){
            if(i==j)continue;
            if(uf.same(i,j)){
                chmin(a[i],a[j]);
            }
        }
    }ll sum = 0;
    rep(i,n) sum += a[i];
    cout << sum <<endl;
}
accuracy: 1
time_ms: 60
memory_kb: 3792
final_rank: 13

code_snippet: #include<iostream>
#include<map>
#include<vector>
#include<queue>
using namespace std;

int main(){
    int n;
    cin >> n;
    map<string, int> pri;
    for(int i = 0; i < n; i++){
        string s;   int x;
        cin >> s >> x;
        pri[s] = x;
    }
    int m;
    cin >> m;
    map<string, vector<string>> v;
    for(int i = 0; i < m; i++){
        string s, t;
        cin >> s >> t;
        v[s].push_back(t);
        v[t].push_back(s);
    }
    int ans = 0;
    map<string, int> visit;
    for(auto p : pri){
        if(visit.count(p.first))  continue;
        int val = p.second, cnt = 1;
        queue<string> q;
        q.push(p.first);
        visit[p.first] = 1;
        while(!q.empty()){
            string s = q.front();   q.pop();
            for(string t : v[s]){
                if(visit.count(t) == 0){
                    cnt++;
                    visit[t] = 1;
                    val = min(val, pri[t]);
                    q.push(t);
                }
            }
        }
        ans += cnt*val;
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4556
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define repi(i,x,n) for(int i = x; i < n; i++)
#define rep(i,n) repi(i,0,n)
using namespace std;
using ll = long long;
const int INF = 1<<30;
const int MOD = 1e9 + 7;
map<string, int> mp;
map<string, vector<string>> G;
map<string, int> used;
int dfs(string s, int &sz)
{
    int res = mp[s];
    sz++;
    for(int u = 0; u < (int)G[s].size(); u++)
    {
        if(used[G[s][u]]) continue;
        used[G[s][u]] = 1;
        res = min(res, dfs(G[s][u], sz));
    }
    return res;
}
signed main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<string> s;
    for(int i = 0; i < n; i++)
    {
        string a; cin >> a;
        s.push_back(a);
        int x; cin >> x;
        mp[a] = x;
    }
    int m; cin >> m;
    for(int i = 0; i < m; i++)
    {
        string s, t; cin >> s >> t;
        G[s].push_back(t);
        G[t].push_back(s);
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
    {
        if(used[s[i]]) continue;
        used[s[i]] = 1;
        int sz = 0;
        ans += dfs(s[i], sz) * sz;
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4648
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#define repi(i,x,n) for(int i = x; i < n; i++)
#define rep(i,n) repi(i,0,n)
using namespace std;
using ll = long long;
const int INF = 1<<30;
const int MOD = 1e9 + 7;
map<string, int> mp;
map<string, vector<string>> G;
map<string, int> used;
int dfs(string s, int &sz)
{
    int res = mp[s];
    sz++;
    for(int u = 0; u < (int)G[s].size(); u++)
    {
        if(used[G[s][u]]) continue;
        used[G[s][u]] = 1;
        res = min(res, dfs(G[s][u], sz));
    }
    return res;
}
signed main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<string> s;
    for(int i = 0; i < n; i++)
    {
        string a; cin >> a;
        s.push_back(a);
        int x; cin >> x;
        mp[a] = x;
    }
    int m; cin >> m;
    for(int i = 0; i < m; i++)
    {
        string s, t; cin >> s >> t;
        G[s].push_back(t);
        G[t].push_back(s);
    }
    int ans = 0;
    for(int i = 0; i < n; i++)
    {
        if(used[s[i]]) continue;
        used[s[i]] = 1;
        int sz = 0;
        ans += dfs(s[i], sz) * sz;
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4584
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define FOR(i, a, b) for(ll i = (a); i < (b); ++i)
#define FORR(i, a, b) for(ll i = (a); i > (b); --i)
#define REP(i, n) for(ll i = 0; i < (n); ++i)
#define REPR(i, n) for(ll i = n; i >= 0; i--)
#define FOREACH(x, a) for(auto &(x) : (a))
#define VECCIN(x)                                                              \
    for(auto &youso_ : (x)) cin >> youso_
#define mp make_pair
#define bitcnt __builtin_popcount
#define SZ(x) ((ll)(x).size())
#define All(a) (a).begin(), (a).end()
template <typename T = long long> inline T IN() {
    T x;
    cin >> x;
    return (x);
}
inline void CIN() {}
template <class Head, class... Tail>
inline void CIN(Head &&head, Tail &&... tail) {
    cin >> head;
    CIN(move(tail)...);
}
#define CINT(...)                                                              \
    int __VA_ARGS__;                                                           \
    CIN(__VA_ARGS__)
#define LCIN(...)                                                              \
    ll __VA_ARGS__;                                                            \
    CIN(__VA_ARGS__)
#define SCIN(...)                                                              \
    string __VA_ARGS__;                                                        \
    CIN(__VA_ARGS__)
#define Yes(a) cout << (a ? "Yes" : "No") << "\n"
#define YES(a) cout << (a ? "YES" : "NO") << "\n"

typedef long long ll;
typedef unsigned long long ul;
typedef vector<int> V;
typedef vector<ll> VL;
typedef pair<ll, ll> PL;
typedef priority_queue<ll> PQ;
typedef priority_queue<ll, V, greater<ll>> PQG;

const int INF = 1e9;
const int MOD = 1e9 + 7;
// const int MOD = 998244353;
const ll LINF = 1e18;

//通常
struct UnionFind {
    V par, rank;
    UnionFind(int size) { init(size); }
    void init(int size) {
        REP(i, size) {
            par.push_back(i);
            rank.push_back(0);
        }
    }
    int root(int x) {
        if(par[x] == x)
            return x;
        else {
            int r = root(par[x]);
            return par[x] = r;
        }
    }
    void unite(int x, int y) {
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(rank[x] < rank[y]) {
            swap(x, y);
        } else {
            if(rank[x] == rank[y]) rank[x]++;
        }
        par[y] = x;
    }
    bool same(int x, int y) { return root(x) == root(y); }
};

ll N, M;
map<ll, ll> val;
map<string, ll> memo;

signed main() {
    cin >> N;
    auto uf = UnionFind(N);
    REP(i, N) {
        SCIN(a);
        LCIN(x);
        memo[a] = i;
        val[i] = x;
    }
    cin >> M;
    REP(i, M) {
        SCIN(s, t);
        uf.unite(memo[s], memo[t]);
    }
    FOREACH(m, memo) {
        ll ro = uf.root(memo[m.first]);
        val[ro] = min(val[ro], val[memo[m.first]]);
    }
    ll ans = 0;
    FOREACH(m, memo) {
        ll ro = uf.root(memo[m.first]);
        ans += val[ro];
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4160
final_rank: 7

code_snippet: #include<algorithm>
#include<climits>
#include<cmath>
#include<iomanip>
#include<iostream>
#include<list>
#include<map>
#include<numeric>
#include<queue>
#include<set>
#include<stack>
#include<utility>
#include<vector>

using namespace std;

#define lint long long
#define REP(i, x, n) for(int i = x ; i < n ; i++)
#define rep(i, n) REP(i, 0, n)
#define repr(i, n) for(int i = n - 1 ; i >= 0 ; i--)
#define SORT(c) sort((c).begin(), (c).end())
#define SORT_INV(c) sort((c).begin(), (c).end(), greater<int>())
#define IINF (int)(1e9+10)
#define LLINF (lint)(1e18+10)

struct unionFind{

    vector<int> par, rank;

    void init(int n){
        par.resize(n);
        rank.resize(n, 0);
        rep(i, n){
            par[i] = i;
        }
        return;
    }

    int root(int x){
        if(par[x] == x){
            return x;
        }else{
            par[x] = root(par[x]);
            return par[x];
        }
    }

    void unite(int x, int y){
        int rx = root(x);
        int ry = root(y);
        if(rx == ry){
            return;
        }
        if(rank[rx] < rank[ry]){
            par[rx] = ry;
        }else if(rank[rx] == rank[ry]){
            par[rx] = ry;
            rank[ry]++;
        }else{
            par[ry] = rx;
        }
        return;
    }

    bool same(int x, int y){
        return root(x) == root(y);
    }

};

int main(){
    int n;
    cin >> n;
    vector<int> x(n);
    map<string, int> mp;
    rep(i, n){
        string a;
        cin >> a;
        mp[a] = i;
        cin >> x[i];
    }
    int m;
    cin >> m;
    unionFind uf;
    uf.init(n);
    rep(i, m){
        string s, t;
        cin >> s >> t;
        uf.unite(mp[s], mp[t]);
    }
    rep(i, n){
        rep(j, n){
            if(uf.same(i, j)){
                x[i] = min(x[i], x[j]);
            }
        }
    }
    int ans = 0;
    rep(i, n){
        ans += x[i];
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3844
final_rank: 14

code_snippet: //http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2664
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define MAX_N 5001
int par[MAX_N], r[MAX_N];//rank


void init(int N)
{
	int i;
	for (i = 0; i < N; i++)
	{
		r[i] = 0;
		par[i] = i;
	}
}

int root(int x)
{
	if (par[x] == x)
	{
		return x;
	}
	else
	{
		return par[x] = root(par[x]);
	}
}

bool same(int x, int y)
{
	return  root(x) == root(y);

}

void unite(int x, int y)
{
	x = root(x);
	y = root(y);
	if (x == y)
	{
		return;
	}
	if (r[x] < r[y])
	{
		par[x] = y;
	}
	else if (r[x]>r[y])
	{
		par[y] = x;
	}
	else if (r[x] == r[y])
	{
		par[x] = y;
		r[y]++;
	}

}
struct _cost {
	string material;
	int material_number;
	int material_cost;
	bool operator<(const _cost& other)const {
		return material_cost < other.material_cost;
	}
};



int main()
{
	int n;//材料の数 ユニオンファインド木の頂点の数
	cin >> n;
	init(n);
	vector<_cost>v(n);//材料とコストの対応を管理
	for (int i = 0; i < n; i++)
	{
		_cost c;
		string str;
		cin >> str;
		c.material = str;
		c.material_number = i;
		int cost;
		cin >> cost;
		c.material_cost = cost;
		v[i] = c;

	}
	sort(v.begin(), v.end());//材料をcostが安い順に並べ替えた
	int m;
	cin >> m;//魔法の種類 辺の数
	vector<vector<int>>edge(m,vector<int>(2));
	for (int i = 0; i < m; i++)
	{
		string str1;
		cin >> str1;
		
		
			for (int j = 0; j < n; j++)
			{
				if (str1 == v[j].material)
				{
					edge[i][0] = v[j].material_number;
		  		}
			}
		
		
		string str2;
		cin >> str2;

		for (int j = 0; j < n; j++)
		{
			if (str2 == v[j].material)
			{
				edge[i][1] = v[j].material_number;
			}
		}

		
	}
	

	for (int i = 0; i < m; i++)
	{
		unite(edge[i][0], edge[i][1]);
	}

	vector<int>check(n,0);//各辺の実質的なコストを管理する
	vector<bool>ok(n, false);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			if (same(v[i].material_number, j)&&(ok[j]==false))
			{
				check[j] = v[i].material_cost;
				ok[j] = true;
			}
		}
	}
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		ans += check[i];
	}
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3508
final_rank: 17

code_snippet: #include <bits/stdc++.h>

const int MOD = 1e9 + 7;
const int iINF = 1000000000;
const long long int llINF = 1000000000000000000;
const double PI = acos(-1.0);
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;
using ll = long long int;
using P = pair<int, int>;
using T = tuple<int, int, int>;
using edge = struct
{
    int to;
    int cost;
};

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

class UnionFind
{
  private:
    vector<int> par;
    vector<int> sizes;

  public:
    UnionFind(int N) : par(N), sizes(N, 1)
    {
        rep(i, N) par[i] = i;
    }

    int find(int x)
    {
        if (x == par[x])
            return x;

        return par[x] = find(par[x]);
    }

    void unite(int x, int y)
    {
        x = find(x);
        y = find(y);

        if (x == y)
            return;

        if (sizes[x] < sizes[y])
            swap(x, y);

        par[y] = x;
        sizes[x] += sizes[y];
    }

    bool same(int x, int y)
    {
        return find(x) == find(y);
    }

    int size(int x)
    {
        return sizes[find(x)];
    }
};

int main()
{
    int N;
    cin >> N;
    vector<int> vec(N);
    map<string, int> mp;
    rep(i, N)
    {
        string a;
        int x;
        cin >> a >> x;
        vec[mp[a] = i] = x;
    }

    UnionFind uf(N);

    int M; 
    cin >> M;
    rep(i, M) 
    {
        string s, t;
        cin >> s >> t;
        if(!uf.same(mp[s], mp[t])) uf.unite(mp[s], mp[t]); 
    }

    rep(i, N) vec[uf.find(i)] = min(vec[uf.find(i)], vec[i]);

    int ans = 0;

    rep(i, N) ans += vec[uf.find(i)];

    cout << ans << endl;
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3856
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;
class UnionFind {
	vector<int>par, sz;
public:
	UnionFind(int n) {
		par = sz = vector<int>(n);
		for (int i = 0; i < n; i++) {
			par[i] = i;
			sz[i] = 1;
		}
	}
	int find(int x) {
		if (par[x] == x)return x;
		return par[x] = find(par[x]);
	}
	void unite(int x, int y) {
		x = find(x); y = find(y);
		if (x == y)return;
		if (sz[x] > sz[y]) {
			par[y] = x;
			sz[x] += sz[y];
		}
		else {
			par[x] = y;
			sz[y] += sz[x];
		}
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
	int size(int x) {
		return sz[find(x)];
	}
};
string a[5000];
int x[5000];
int Min[5000],cnt[5000];
int main(){
	int n;scanf("%d",&n);
	map<string,int>mp;
	rep(i,n){
		cin>>a[i]>>x[i];
		int b=mp.size();
		mp[a[i]]=b;
	}
	int m;scanf("%d",&m);
	UnionFind uf(n);
	rep(i,m){
		string s,t;cin>>s>>t;
		uf.unite(mp[s],mp[t]);
	}
	memset(Min,0x3f,sizeof(Min));
	rep(i,n){
		Min[uf.find(i)]=min(Min[uf.find(i)],x[i]);
		cnt[uf.find(i)]++;
	}
	int ans=0;
	rep(i,n)ans+=Min[i]*cnt[i];
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4012
final_rank: 6

code_snippet: #include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<functional>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<numeric>
#include<limits>
#include<iterator>

#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define rep(i,n) for(int i=0; i<n; i++)
#define FOR(i,a,n) for(int i=a; i<n; i++)

using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef pair<ll, char> plc;
typedef pair<string, string> pss;

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;
	}
};


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

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

	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)];

	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3780
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
//---------------------------------------------------------------------------------------------------
struct Data {
    int n, mi;
    Data() {
        n = 1;
        mi = 10101010;
    }
    void add(Data &d) {
        n += d.n;
        mi = min(mi, d.mi);
    }
};
struct UnionFindWithData {
    vector<int> par; vector<Data> dat;
    UnionFindWithData(int NV) { par.clear(); dat.resize(NV); rep(i, 0, NV) par.push_back(i); }
    void reset() { rep(i, 0, dat.size()) dat[i] = Data(); rep(i, 0, par.size()) par[i] = i; }
    pair<int, Data> operator[](int x) { if (par[x] == x) return { x, dat[x] };
        auto p = operator[](par[x]);par[x] = p.first;return p;}
    void operator()(int x, int y) {
        x = operator[](x).first; y = operator[](y).first;if(x!=y)par[x]=y,dat[y].add(dat[x]);}};
/*---------------------------------------------------------------------------------------------------
????????????????????????????????? ??§?????§  
??????????????? ??§?????§ ???????´<_??? ?????? Welcome to My Coding Space!
???????????? ??? ?´_???`??????/??? ???i     
?????????????????????????????? ???  |???|     
????????? /?????? /??£??£??£??£/??????|  
??? ???_(__??????/???    ???/ .| .|????????????  
??? ????????????/????????????/??????u??????  
---------------------------------------------------------------------------------------------------*/




int N, M;
map<string, int> dic;
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> N;

    UnionFindWithData uf(N);
    rep(i, 0, N) {
        string s; int x; cin >> s >> x;
        dic[s] = i;
        uf.dat[i].mi = x;
    }

    cin >> M;

    rep(i, 0, M) {
        string a, b; cin >> a >> b;
        int aa = dic[a], bb = dic[b];
       // printf("%d-%d\n", aa, bb);
        uf(aa, bb);
    }

    int ans = 0;
    rep(i, 0, N) if (uf[i].first == i) {
        auto data = uf[i].second;
        ans += data.mi * data.n;
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3808
final_rank: 3

code_snippet: #include<iostream>
#include<string>
#include<map>
using namespace std;
struct UF{
  map<string,string> food;
  map<string,int> cost;
  void init(string x,int y){
    food[x] = x;
    cost[x] = y;
  }
  void unite(string x,string y){
    x = find(x);
    y = find(y);
    if(cost[x] > cost[y]) food[x] = food[y];
    if(cost[y] > cost[x]) food[y] = food[x];
  }
  string find(string x){
    if(x != food[x]) x = find(food[x]);
    return x;
  }
  int co(string x){
    return cost[find(x)];
  }
};
int main(){
  int n,m,x;
  string a[5001],s,t;
  UF uf;
  cin >> n;
  for(int i=0;i<n;i++){
    cin >> a[i] >> x;
    uf.init(a[i],x);
  }
  cin >> m;
  while(m--){
    cin >> s >> t;
    uf.unite(s,t);
  }
  long long ans = 0;
  for(int i=0;i<n;i++) ans += uf.co(a[i]);
  cout << ans << endl;
  return (0);
}
accuracy: 0.7076923076923077
time_ms: 10
memory_kb: 3956
final_rank: 19

code_snippet: #include<iostream>
#include<string>
#include<map>
using namespace std;
struct UF{
  map<string,string> food;
  map<string,int> cost;
  void init(string x,int y){
    food[x] = x;
    cost[x] = y;
  }
  void unite(string x,string y){
    x = find(x);
    y = find(y);
    if(cost[x] > cost[y]) food[x] = food[y];
    if(cost[y] > cost[x]) food[y] = food[x];
  }
  string find(string x){
    if(x != food[x]){
      if(cost[x] > cost[food[x]]) cost[x] = cost[food[x]];
      if(cost[food[x]] > cost[x]) cost[food[x]] = cost[x];
      x = find(food[x]);
    }
    return x;
  }
  int co(string x){
    return cost[find(x)];
  }
};
int main(){
  int n,m,x;
  string a[5001],s,t;
  UF uf;
  cin >> n;
  for(int i=0;i<n;i++){
    cin >> a[i] >> x;
    uf.init(a[i],x);
  }
  cin >> m;
  while(m--){
    cin >> s >> t;
    uf.unite(s,t);
  }
  int ans = 0;
  for(int i=0;i<n;i++) ans += uf.co(a[i]);
  cout << ans << endl;
  return (0);
}
accuracy: 0.7076923076923077
time_ms: 10
memory_kb: 4016
final_rank: 20

code_snippet: #include<iostream>
#include<string>
#include<map>
using namespace std;
struct UF{
  map<string,string> food;
  map<string,int> cost;
  void init(string x,int y){
    food[x] = x;
    cost[x] = y;
  }
  void unite(string x,string y){
    x = find(x);
    y = find(y);
    if(cost[x] > cost[y]){
      food[x] = food[y];
      cost[x] = cost[y];
    }
    if(cost[y] > cost[x]){
      food[y] = food[x];
      cost[y] = cost[x];
    }
  }
  string find(string x){
    if(x != food[x]) x = find(food[x]);
    return x;
  }
  int co(string x){
    return cost[find(x)];
  }
};
int main(){
  int n,m,x;
  string a[5001],s,t;
  UF uf;
  cin >> n;
  for(int i=0;i<n;i++){
    cin >> a[i] >> x;
    uf.init(a[i],x);
  }
  cin >> m;
  while(m--){
    cin >> s >> t;
    uf.unite(s,t);
  }
  int ans = 0;
  for(int i=0;i<n;i++) ans += uf.co(a[i]);
  cout << ans << endl;
  return (0);
}
accuracy: 0.7076923076923077
time_ms: 10
memory_kb: 3908
final_rank: 18

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
typedef long long int ll;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

int* parent,*height;

struct Info{
	Info(){
		cost = -1;
	}
	char name[11];
	int cost;
};

bool strCmp(char* base, char* comp){
	int length1 = 0,length2 = 0;
	for(int i=0;base[i] != '\0'; i++)length1++;
	for(int i=0;comp[i] != '\0'; i++)length2++;
	if(length1 != length2)return false;

	for(int i=0;base[i] != '\0'; i++){
		if(base[i] != comp[i])return false;
	}
	return true;
}

int getParent(int id){
	if(parent[id] == id)return id;
	else{
		return parent[id] = getParent(parent[id]);
	}
}

bool isSame(int left,int right){
	return getParent(left) == getParent(right);
}

void unite(int left,int right){
	int left_parent = getParent(left);
	int right_parent = getParent(right);

	if(left_parent == right_parent)return;

	if(height[left_parent] >= height[right_parent]){
		if(height[left_parent] == height[right_parent]){
			height[left_parent]++;
		}
		parent[right_parent] = left_parent;
	}else{
		parent[left_parent] = right_parent;
	}
}


int main(){

	int N,M;
	scanf("%d",&N);
	parent = new int[N];
	height = new int[N];

	int* min_cost = new int[N];

	Info info[N];

	for(int i = 0; i < N; i++){
		parent[i] = i;
		height[i] = 0;
	}

	for(int i = 0; i < N; i++){
		scanf("%s %d",info[i].name,&info[i].cost);
		min_cost[i] = info[i].cost;
	}

	char left[11],right[11];
	int left_id,right_id;

	scanf("%d",&M);

	for(int loop = 0; loop < M; loop++){
		scanf("%s %s",left,right);

		for(int i = 0; i < N; i++){
			if(strCmp(left,info[i].name)){
				left_id = i;
				break;
			}
		}

		for(int i = 0; i < N; i++){
			if(strCmp(right,info[i].name)){
				right_id = i;
				break;
			}
		}

		unite(left_id,right_id);
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(isSame(i,k)){
				min_cost[i] = min(min_cost[i],info[k].cost);
			}
		}
	}

	int sum = 0;
	for(int i = 0; i < N; i++)sum += min_cost[i];

	printf("%d\n",sum);

	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 2872
final_rank: 15

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

using P = pair<int, int>;

class union_find {
public:
    union_find(int n, vector<int> const& a)
        : par_(n, -1),
          a_(a)
    {}
    void init(int n) {
        par_.assign(n, -1);
        a_.assign(n, -1);
    }

    int root(int x) {
        return par_[x] < 0 ? x : par_[x] = root(par_[x]);
    }

    bool unite(int x, int y) {
        x = root(x); y = root(y);
        if(x == y) {
            return false;
        } else {
            if(par_[x] < par_[y]) {
                par_[x] += par_[y];
                par_[y] = x;
                a_[x] = min(a_[x], a_[y]);
            } else {
                par_[y] += par_[x];
                par_[x] = y;
                a_[y] = min(a_[y], a_[x]);
            }
            return true;
        }
    }

    bool same(int x, int y) {
        return root(x) == root(y);
    }

    int size(int x) {
        return -par_[root(x)];
    }

    int get(int x) {
        return a_[root(x)];
    }

private:
    std::vector<int> par_;
    vector<int> a_;
};

using P = pair<int, int>;

int main() {
    int N;
    cin >> N;
    map<string, int> idx;
    vector<int> v(N);
    for(int i=0; i<N; ++i) {
        string a;
        int x;
        cin >> a >> x;
        idx[a] = i;
        v[i] = x;
    }
    union_find uf(N, v);

    int M;
    cin >> M;
    for(int i=0; i<M; ++i) {
        string s, t;
        cin >> s >> t;
        uf.unite(idx[s], idx[t]);
    }

    int res = 0;
    for(int i=0; i<N; ++i) {
        res += uf.get(i);
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3752
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define sz(a) ((int)(a).size())

const int INF = 1e9;

struct UFnode
{
  string value_;
  int rank_, p_, index_, size_;
  UFnode(string value) : value_(value), rank_(0), p_(-1), size_(1) {}
  int size() const { return size_; }
};

struct UF
{
  vector<UFnode> ufnodes_;
  // mapping a value to its index in vector
  map<string, int> value_to_index_;
  // the number of components
  int size_;

  UF() : size_(0) {}
  int size() const { return size_; }
  // Returns the number of nodes in the tree in which value resides
  int tree_size(string value)
  {
    if (value_to_index_.count(value) == 0) { return 0; }
    int pix = ufnodes_[value_to_index_[value]].p_;
    return ufnodes_[pix].size();
  }

  void make_set(string value)
  {
    UFnode node(value);
    ufnodes_.push_back(node);
    int ix = ufnodes_.size() - 1;
    ufnodes_[ix].index_ = ufnodes_[ix].p_ = value_to_index_[value] = ix;
    ++size_;
  }

  // Return index of the root of the tree to which value belongs.
  int find_set(string value, int index = -1)
  {
    if (index == -1) {
      if (value_to_index_.count(value) == 0) { return -1; }
      index = value_to_index_[value];
    }
    if (ufnodes_[index].p_ != index) {
      ufnodes_[index].p_ = find_set(ufnodes_[ufnodes_[index].p_].value_, ufnodes_[index].p_);
    }
    return ufnodes_[index].p_;
  }

  void unite(string x, string y)
  {
    int s1 = find_set(x), s2 = find_set(y);
    if ((s1 == s2) || (s1 == -1) || (s2 == -1)) { return; }
    if (ufnodes_[s1].rank_ > ufnodes_[s2].rank_) {
      // connect ufnodes_[s2] to ufnodes_[s1]
      ufnodes_[s2].p_ = s1;
      ufnodes_[s1].size_ += ufnodes_[s2].size_;
    }
    else {
      // connect ufnodes_[s1] to ufnodes_[s2]
      ufnodes_[s1].p_ = s2;
      ufnodes_[s2].size_ += ufnodes_[s1].size_;
      if (ufnodes_[s1].rank_ == ufnodes_[s2].rank_) { ++ufnodes_[s2].rank_; }
    }
    --size_;
  }

  bool is_connected(string x, string y) { return find_set(x) == find_set(y); }
};

int main()
{
  vector<string> stuff;
  vector<int> prices;
  int n = 0;
  UF uf;
  fscanf(stdin, "%d", &n);
  for (int i = 0; i < n; ++i) {
    string s;
    int p;
    cin >> s >> p;
    prices.push_back(p);
    stuff.push_back(s);
    uf.make_set(s);
  }
  int m = 0;
  fscanf(stdin, "%d", &m);
  for (int i = 0; i < m; ++i) {
    string s, t;
    cin >> s >> t;
    uf.unite(s, t);
  }
  vector<int> min_prices(n, INF);
  for (int i = 0; i < sz(stuff); ++i) {
    int r = uf.find_set(stuff[i]);
    min_prices[r] = min(min_prices[r], prices[i]);
  }
  int ans = 0;
  for (int i = 0; i < sz(stuff); ++i) {
    int r = uf.find_set(stuff[i]);
    ans += min_prices[r];
  }
  fprintf(stdout, "%d\n", ans);
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3888
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define sz(a) ((int)(a).size())

const int INF = 1e9;

struct UFnode
{
  string value_;
  int rank_, p_, index_, size_;
  UFnode(string value) : value_(value), rank_(0), p_(-1), size_(1) {}
  int size() const { return size_; }
};

struct UF
{
  vector<UFnode> ufnodes_;
  // mapping a value to its index in vector
  map<string, int> value_to_index_;
  // the number of components
  int size_;

  UF() : size_(0) {}
  int size() const { return size_; }
  // Returns the number of nodes in the tree in which value resides
  int tree_size(string value)
  {
    if (value_to_index_.count(value) == 0) { return 0; }
    int pix = ufnodes_[value_to_index_[value]].p_;
    return ufnodes_[pix].size();
  }

  void make_set(string value)
  {
    UFnode node(value);
    ufnodes_.push_back(node);
    int ix = ufnodes_.size() - 1;
    ufnodes_[ix].index_ = ufnodes_[ix].p_ = value_to_index_[value] = ix;
    ++size_;
  }

  // Return index of the root of the tree to which value belongs.
  int find_set(string value, int index = -1)
  {
    if (index == -1) {
      if (value_to_index_.count(value) == 0) { return -1; }
      index = value_to_index_[value];
    }
    if (ufnodes_[index].p_ != index) {
      ufnodes_[index].p_ = find_set(ufnodes_[ufnodes_[index].p_].value_, ufnodes_[index].p_);
    }
    return ufnodes_[index].p_;
  }

  void unite(string x, string y)
  {
    int s1 = find_set(x), s2 = find_set(y);
    if ((s1 == s2) || (s1 == -1) || (s2 == -1)) { return; }
    if (ufnodes_[s1].rank_ > ufnodes_[s2].rank_) {
      // connect ufnodes_[s2] to ufnodes_[s1]
      ufnodes_[s2].p_ = s1;
      ufnodes_[s1].size_ += ufnodes_[s2].size_;
    }
    else {
      // connect ufnodes_[s1] to ufnodes_[s2]
      ufnodes_[s1].p_ = s2;
      ufnodes_[s2].size_ += ufnodes_[s1].size_;
      if (ufnodes_[s1].rank_ == ufnodes_[s2].rank_) { ++ufnodes_[s2].rank_; }
    }
    --size_;
  }

  bool is_connected(string x, string y) { return find_set(x) == find_set(y); }
};

int main()
{
  vector<string> stuff;
  map<string, int> prices;
  int n = 0;
  UF uf;
  fscanf(stdin, "%d", &n);
  for (int i = 0; i < n; ++i) {
    string s;
    int p;
    cin >> s >> p;
    prices[s] = p;
    stuff.push_back(s);
    uf.make_set(s);
  }
  int m = 0;
  fscanf(stdin, "%d", &m);
  for (int i = 0; i < m; ++i) {
    string s, t;
    cin >> s >> t;
    uf.unite(s, t);
  }
  map<int, int> min_prices;
  for (int i = 0; i < sz(stuff); ++i) {
    int r = uf.find_set(stuff[i]);
    if (min_prices.count(r) == 0) {
      min_prices[r] = prices[stuff[i]];
    }
    else {
      min_prices[r] = min(min_prices[r], prices[stuff[i]]);
    }
  }
  int ans = 0;
  for (int i = 0; i < sz(stuff); ++i) {
    int r = uf.find_set(stuff[i]);
    ans += min_prices[r];
  }
  fprintf(stdout, "%d\n", ans);
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4396
final_rank: 8