답안 #603338

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
603338 2022-07-24T03:44:57 Z GusterGoose27 철인 이종 경기 (APIO18_duathlon) C++11
0 / 100
227 ms 48080 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;
int rt;
vector<int> cent_graph[treeMAXN];
int sz[treeMAXN];
vector<int> in_decomp;
vector<int> in_stree[treeMAXN];
ll smult[treeMAXN];
ll psum[treeMAXN];

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

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

void find_cut(int i, 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, i);
		lp[i] = min(lp[i], lp[next]);
		if (lp[next] >= depth[i]) is_point = 1;
	}
	if (i == 0) {
		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 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);
		// cout << 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];
	}
	// 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;
	}
	// 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;
	find_cut(0);
	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) {
		// 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);
		}
		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);
	rt = make_decomp(0);
	fill(vis, vis+n, 0);
	// cerr << endl;
	make_ans(rt);
	ll p2sum = 0;
	ll over_sum = 0;
	ll ex = 0;
	for (int i = 0; i < n; i++) {
		ll cur = bcc_sz[i];
		p2sum += cur*(cur-1);
		over_sum += cur;
		ex += 2*cur*(cur-1);
	}
	ans += p2sum*over_sum-ex;
	cout << ans << "\n";
}
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 22280 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 22280 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 67 ms 38708 KB Output is correct
2 Correct 87 ms 38776 KB Output is correct
3 Incorrect 63 ms 32432 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 22484 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 210 ms 48080 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 14 ms 22496 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 227 ms 48072 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 22280 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 12 ms 22280 KB Output isn't correct
2 Halted 0 ms 0 KB -