답안 #219487

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
219487 2020-04-05T11:43:44 Z atoiz 조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2) C++14
0 / 100
13 ms 11264 KB
/*input
3 5
2 1
1 3
3 2
1 2
3 2

*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <stack>
#include <unordered_set>
#include <unordered_map>
#include <ctime>

using namespace std;

const int MAXN = 100007;
int N, M;
int root[MAXN];
int64_t E = 0, cnt[MAXN], deg_in[MAXN], deg_out[MAXN];
unordered_map<int, unordered_set<int>> edges[MAXN];
unordered_set<int> back_edges[MAXN];

stack<pair<int, int>> join_stack;

void init()
{
	for (int u = 1; u <= N; ++u) cnt[u] = 1, root[u] = u;
}

int get_root(int u) { return (root[u] == u ? u : root[u] = get_root(root[u])); }

void delete_edge(int u, int v)
{
	auto it = edges[u].find(v);
	assert(it != edges[u].end());

	int64_t cur = it->second.size() * cnt[v];
	deg_out[u] -= it->second.size(), deg_in[v] -= it->second.size(), E -= cur;
	edges[u].erase(it);
	back_edges[v].erase(u);
}

void add_edge(int u, int v, unordered_set<int> sources)
{
	back_edges[v].insert(u);
	for (int x : sources) {
		if (edges[u][v].find(x) == edges[u][v].end()) {
			++deg_out[u], ++deg_in[v], E += cnt[v];
			edges[u][v].insert(x);
		}
	}	
}

void join(int u, int v)
{
	u = get_root(u), v = get_root(v);
	if (u == v) return;

	if (deg_in[u] + deg_out[u] < deg_in[v] + deg_out[v]) swap(u, v);

	// between u and v
	if (edges[u].find(v) != edges[u].end()) delete_edge(u, v);
	if (edges[v].find(u) != edges[v].end()) delete_edge(v, u);
	E += cnt[u] * cnt[v] * 2;
	// cout << "X " << E << endl;

	auto edges_v = edges[v];
	for (auto batch : edges_v) {
		int w = batch.first;
		delete_edge(v, w);
		if (back_edges[u].find(w) != back_edges[u].end()) join_stack.emplace(u, w);
		else {
			add_edge(u, w, batch.second);
		}
	}

	auto back_edges_v = back_edges[v];
	for (int w : back_edges_v) {
		delete_edge(w, v);
		if (back_edges[w].find(u) != back_edges[w].end()) join_stack.emplace(u, w);
		else {
			auto sources = edges[w][v];
			add_edge(w, u, sources);
		}
	}

	E += cnt[v] * deg_in[u];
	cnt[u] += cnt[v];
	root[v] = u;
}

void query(int u, int v)
{
	unordered_set<int> sources = {u};
	int root_u = get_root(u), root_v = get_root(v);
	if (root_u == root_v) return;
	add_edge(root_u, root_v, sources);
	// cout << "Y " << E << endl;

	if (back_edges[root_u].find(root_v) != back_edges[root_u].end()) {
		join_stack.emplace(root_u, root_v);
	}

	while (!join_stack.empty()) {
		auto p = join_stack.top();
		join_stack.pop();
		join(p.first, p.second);
		// cout << "join " << p.first << ' ' << p.second << ": " << E << endl;
	}
}

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin >> N >> M;
	init();
	while (M--) {
		int u, v;
		cin >> u >> v;
		query(u, v);
		cout << E << '\n';
	}
	cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 11264 KB Output is correct
2 Incorrect 12 ms 11264 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 11264 KB Output is correct
2 Incorrect 12 ms 11264 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 11264 KB Output is correct
2 Incorrect 12 ms 11264 KB Output isn't correct
3 Halted 0 ms 0 KB -