답안 #603348

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
603348 2022-07-24T04:00:07 Z GusterGoose27 철인 이종 경기 (APIO18_duathlon) C++11
0 / 100
725 ms 1048576 KB
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1e5;
const int MAXM = 2e5;
const int treeMAXN = 2e5; // n bccs, n cut nodes

typedef long long ll;

vector<int> tree_edges[treeMAXN];
vector<int> edges[MAXN];
int n, m;
vector<int> cut_verts;
bool is_cut[MAXN];
int depth[MAXN];
int lp[MAXN];
unordered_set<int> bccs_in[MAXN];
int bcc_sz[treeMAXN];
int t = 0;
bool vis[treeMAXN];
ll ans = 0;
vector<int> rts;
vector<vector<int>> comps;
vector<int> cent_graph[treeMAXN];
int sz[treeMAXN];
vector<int> in_decomp;
vector<int> in_stree[treeMAXN];
ll smult[treeMAXN];
ll psum[treeMAXN];
bool flag = 0;

void print(vector<int> &v) {
	if (!flag) return;
	for (int i: v) {
		cout << i << " ";
	}
	cout << endl;
}

void print(unordered_set<int> &v) {
	if (!flag) return;
	for (int i: v) {
		cout << i << " ";
	}
	cout << endl << endl;
}

void find_cut(int i, int s, int p = -1) {
	lp[i] = depth[i];
	int c = 0;
	bool is_point = 0;
	for (int next: edges[i]) {
		if (next == p) continue;
		if (depth[next] != -1) {
			lp[i] = min(lp[i], depth[next]);
			continue;
		}
		c++;
		depth[next] = 1+depth[i];
		find_cut(next, s, i);
		lp[i] = min(lp[i], lp[next]);
		if (lp[next] >= depth[i]) is_point = 1;
	}
	if (i == s) {
		if (c > 1) {
			cut_verts.push_back(i);
			is_cut[i] = 1;
		}
	}
	else if (is_point) {
		cut_verts.push_back(i);
		is_cut[i] = 1;
	}
}

void make_bcc(int s) {
	vis[s] = 1;
	bcc_sz[t]++;
	for (int next: edges[s]) {
		if (vis[next]) continue;
		if (is_cut[next]) {
			bccs_in[next].insert(t);
			continue;
		}
		make_bcc(next);
	}
}

void make_sz(int cur, int p = -1) {
	sz[cur] = 1;
	for (int next: tree_edges[cur]) {
		if (vis[next] || next == p) continue;
		make_sz(next, cur);
		sz[cur] += sz[next];
	}
}

int make_decomp(int cur) {
	make_sz(cur);
	int tot = sz[cur];
	bool f = 1;
	int p = -1;
	while (f) {
		f = 0;
		for (int next: tree_edges[cur]) {
			if (vis[next] || next == p) continue;
			if (sz[next] > tot/2) {
				p = cur;
				cur = next;
				f = 1;
				break;
			}
		}
	}
	vis[cur] = 1;
	for (int next: tree_edges[cur]) {
		if (!vis[next]) cent_graph[cur].push_back(make_decomp(next));
	}
	return cur;
}

void get_comp(int i, vector<int> &v, int p = -1) {
	v.push_back(i);
	for (int next: tree_edges[i]) {
		if (next == p) continue;
		get_comp(next, v, i);
	}
}

void dfs(int cur, int p, ll rtsum, int stree) {
	rtsum += bcc_sz[cur];
	ll cval = bcc_sz[cur];
	smult[cur] = cval*rtsum;
	psum[cur] = cval;
	in_decomp.push_back(cur);
	in_stree[stree].push_back(cur);
	for (int next: tree_edges[cur]) {
		if (vis[next] || next == p) continue;
		dfs(next, cur, rtsum, stree);
	}
}

void make_ans(int cur) {
	vis[cur] = 1;
	in_decomp.clear();
	in_decomp.push_back(cur);
	ll rtval = bcc_sz[cur];
	smult[cur] = rtval*rtval;
	psum[cur] = rtval;
	for (int next: tree_edges[cur]) {
		if (vis[next]) continue;
		dfs(next, cur, rtval, next);
		if (flag) cerr << next << endl;
		print(in_stree[next]);
	}
	print(in_decomp);
	ll s = 0;
	ll p = 0;
	ll q = 0;
	for (int v: in_decomp) {
		s += smult[v];
		p += psum[v];
		q += psum[v]*psum[v];
	}
	if (flag) cout << s << ' ' << p << ' ' << q << endl;
	ll add = 2*s*p-p*p*rtval-2*p*q+rtval*rtval*rtval;
	for (int next: tree_edges[cur]) {
		if (vis[next]) continue;
		s = 0;
		p = 0;
		q = 0;
		for (int v: in_stree[next]) {
			s += smult[v];
			p += psum[v];
			q += psum[v]*psum[v];
		}
		add -= 2*s*p-p*p*rtval-2*p*q;
	}
	if (flag) cout << add << endl << endl;
	ans += add;
	for (int next: cent_graph[cur]) make_ans(next);
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		int x, y; cin >> x >> y; x--; y--;
		edges[x].push_back(y);
		edges[y].push_back(x);
	}
	fill(depth, depth+n, -1);
	depth[0] = 0;
	for (int i = 0; i < n; i++) {
		if (!vis[i]) find_cut(i, i);
	}
	for (int i = 0; i < n; i++) {
		if (is_cut[i] || vis[i]) continue;
		make_bcc(i); t++;
	}
	assert(t+cut_verts.size() <= treeMAXN);
	map<int, int> pos_of;
	int d = 0;
	for (int v: cut_verts) {
		pos_of[v] = d;
		d++;
	}
	for (int v: cut_verts) {
		if (flag) cout << v << endl;
		print(bccs_in[v]);
		for (int next: edges[v]) {
			if (is_cut[next]) tree_edges[pos_of[v]+t].push_back(pos_of[next]+t);
		}
		for (int next: bccs_in[v]) {
			tree_edges[pos_of[v]+t].push_back(next);
			tree_edges[next].push_back(pos_of[v]+t);
			ll csize = bcc_sz[next];
			ans += csize*(csize-1);
		}
		bcc_sz[pos_of[v]+t] = 1;
	}
	n = t+cut_verts.size();
	for (int i = 0; i < n; i++) print(tree_edges[i]);
	fill(vis, vis+n, 0);
	for (int i = 0; i < n; i++) {
		if (vis[i]) continue;
		rts.push_back(make_decomp(i));
		vector<int> v;
		get_comp(i, v);
		comps.push_back(v);
	}
	fill(vis, vis+n, 0);
	if (flag) cerr << endl;
	for (int rt: rts) make_ans(rt);
	for (vector<int> comp: comps) {
		ll p2sum = 0;
		ll over_sum = 0;
		ll ex = 0;
		for (int i: comp) {
			ll cur = bcc_sz[i];
			p2sum += cur*(cur-1);
			over_sum += cur;
			ex += (cur+2)*cur*(cur-1);
		}
		ans += 2*p2sum*over_sum-ex;
	}
	cout << ans << "\n";
}
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 22228 KB Output is correct
2 Correct 12 ms 22228 KB Output is correct
3 Correct 11 ms 22228 KB Output is correct
4 Correct 11 ms 22228 KB Output is correct
5 Correct 11 ms 22224 KB Output is correct
6 Correct 11 ms 22264 KB Output is correct
7 Runtime error 725 ms 1048576 KB Execution killed with signal 9
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 22228 KB Output is correct
2 Correct 12 ms 22228 KB Output is correct
3 Correct 11 ms 22228 KB Output is correct
4 Correct 11 ms 22228 KB Output is correct
5 Correct 11 ms 22224 KB Output is correct
6 Correct 11 ms 22264 KB Output is correct
7 Runtime error 725 ms 1048576 KB Execution killed with signal 9
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 110 ms 38912 KB Output is correct
2 Correct 107 ms 38832 KB Output is correct
3 Incorrect 171 ms 43640 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 14 ms 22552 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 236 ms 49020 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 14 ms 22436 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 235 ms 49032 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 22228 KB Output is correct
2 Correct 12 ms 22228 KB Output is correct
3 Correct 11 ms 22228 KB Output is correct
4 Correct 11 ms 22228 KB Output is correct
5 Correct 11 ms 22224 KB Output is correct
6 Correct 11 ms 22264 KB Output is correct
7 Runtime error 725 ms 1048576 KB Execution killed with signal 9
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 12 ms 22228 KB Output is correct
2 Correct 12 ms 22228 KB Output is correct
3 Correct 11 ms 22228 KB Output is correct
4 Correct 11 ms 22228 KB Output is correct
5 Correct 11 ms 22224 KB Output is correct
6 Correct 11 ms 22264 KB Output is correct
7 Runtime error 725 ms 1048576 KB Execution killed with signal 9
8 Halted 0 ms 0 KB -