結果

問題 No.1293 2種類の道路
ユーザー 👑 rin204rin204
提出日時 2022-12-25 17:55:32
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 3,121 bytes
コンパイル時間 2,926 ms
コンパイル使用メモリ 216,124 KB
実行使用メモリ 16,596 KB
最終ジャッジ日時 2023-08-12 08:16:42
合計ジャッジ時間 6,770 ms
ジャッジサーバーID
(参考情報)
judge13 / judge14
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,384 KB
testcase_01 AC 2 ms
4,384 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 2 ms
4,380 KB
testcase_04 AC 2 ms
4,384 KB
testcase_05 AC 1 ms
4,380 KB
testcase_06 AC 2 ms
4,380 KB
testcase_07 AC 2 ms
4,384 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 AC 36 ms
6,712 KB
testcase_22 AC 36 ms
6,676 KB
testcase_23 AC 32 ms
6,676 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "A.cpp"
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl "\n"

void print(){
	cout << '\n';
}

template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
	cout << head;
	if (sizeof...(Tail)) cout << ' ';
  	print(forward<Tail>(tail)...);
}

template<typename T>
void print(vector<T> &A){
	int n = A.size();
	for(int i = 0; i < n; i++){
		cout << A[i];
		if(i == n - 1) cout << '\n';
		else cout << ' ';
	}
}

template<typename T, typename S>
void prisep(vector<T> &A, S sep){
	int n = A.size();
	for(int i = 0; i < n; i++){
		cout << A[i];
		if(i == n - 1) cout << '\n';
		else cout << sep;
	}
}

template<typename T>
void print(vector<vector<T>> &A){
	for(auto &row: A) print(row);
}

#line 3 "Library/C++/data_structure/RollbackUnionFind.hpp"
using namespace std;

struct RollbackUnionFind{
    int n;
    vector<int> par;
    int group;
    stack<pair<int, int>> history;
    int inner_snap;

    RollbackUnionFind(int n) : n(n){
        par.assign(n, -1);
        group = n;
        inner_snap = 0;
    }

    int find(int x){
        if(par[x] < 0) return x;
        else return find(par[x]);
    }

    bool unite(int x, int y){
        x = find(x);
        y = find(y);
        history.push({x, par[x]});
        history.push({y, par[y]});
        if(x == y) return false;
        if(par[x] > par[y]) swap(x, y);
        group--;
        par[x] += par[y];
        par[y] = x;
        return true;
    }

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

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

    vector<int> roots(){
        vector<int> ret;
        for(int i = 0; i < n; i++){
            if(i == find(i)) ret.push_back(i);
        }
        return ret;
    }

    void undo(){
        pair<int, int> tmp = history.top(); history.pop();
        int x = tmp.first;
        par[tmp.first] = tmp.second;
        tmp = history.top(); history.pop();
        par[tmp.first] = tmp.second;
        if(x != tmp.first) group++;
    }

    void snapshot(){
        inner_snap = (history.size()) >> 1;
    }

    int get_state(){
        return (history.size()) >> 1;
    }

    void rollback(int state=-1){
        if(state == -1) state = inner_snap;
        state <<= 1;
        assert(state <= history.size());
        while(state < history.size()) undo();
    }
};
#line 43 "A.cpp"

void solve(){
	int n, d, w;
	cin >> n >> d >> w;
	RollbackUnionFind UF1(n);
	RollbackUnionFind UF2(n);
	int a, b;
	for(int i = 0; i < d; i++){
		cin >> a >> b;
		UF1.unite(a - 1, b - 1);
	}
	for(int i = 0; i < w; i++){
		cin >> a >> b;
		UF2.unite(a - 1, b - 1);
	}

	int ans = -n;
	map<int, vector<int>> mp;
	for(int i = 0; i < n; i++){
		mp[UF1.find(i)].push_back(i);
	}
	for(auto tmp:mp){
		auto group = tmp.second;
		int u = group[0];
		int ver = UF2.get_state();
		for(auto v:group){
			if(u == v) continue;
			UF2.unite(u, v);
		}
		ans += UF1.size(u) * UF2.size(u);
		UF2.rollback(ver);
	}
	print(ans);
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    int t;
    t = 1;
    // cin >> t;
    while(t--) solve();
	return 0;
}
0