結果

問題 No.1769 Don't Stop the Game
ユーザー polylogK
提出日時 2021-10-29 22:40:59
言語 C++17(gcc12)
(gcc 12.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 3,247 bytes
コンパイル時間 7,051 ms
コンパイル使用メモリ 118,220 KB
最終ジャッジ日時 2025-01-25 09:16:09
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 17 TLE * 11
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

// #include <testlib.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>

#define NDEBUG

using i64 = long long;

bool deleted[200'000];
int size[200'000];

struct solve_t {
	std::vector<std::vector<int>> g;
	std::vector<int> a, b, c;

	solve_t(int n): g(n) {}
	void add_edge(int u, int v, int w) {
		g[u].push_back(a.size());
		g[v].push_back(a.size());
		a.push_back(u);
		b.push_back(v);
		c.push_back(w);
	}

	i64 solve(int start = 0) {
		i64 answer = (i64)g.size() * ((i64)g.size() - 1);

		auto solve = [&](auto&& solve, int root, int all) -> void {
			int centroid_tmp = -1;
			auto calc_size = [&](auto&& dfs, int v, int par) -> int {
				size[v] = 1;
				int tmp = v;
				for(int id: g[v]) {
					int to = v ^ a[id] ^ b[id];
					if(to == par or deleted[to]) continue;

					int sub_size = dfs(dfs, to, v);
					if(sub_size * 2 > all) tmp = -1;
					size[v] += sub_size;
				}
				if(2 * (all - size[v]) > all) tmp = -1;
				if(tmp != -1) centroid_tmp = tmp;
				return size[v];
			}; calc_size(calc_size, root, -1);
			int centroid = centroid_tmp;
			calc_size(calc_size, centroid, -1);

			for(int loop = 0; loop < 2; loop++) {
				std::map<int, int> map;
				for(int id: g[centroid]) {
					int to = centroid ^ a[id] ^ b[id];
					if(deleted[to]) continue;

					{ // counting 0-xor paths
						std::set<int> xor_path; xor_path.insert(0);
						auto dfs = [&](auto&& dfs, int v, int par, int xor_val) -> void {
							if(loop and xor_path.count(xor_val)) { // [u-centroid]
								answer -= size[centroid] - size[to];
							}

							bool append = false;
							if(!xor_path.count(xor_val)) {
								answer -= map[xor_val];

								xor_path.insert(xor_val);
								append = true;
							}

							for(int id: g[v]) {
								int to = v ^ a[id] ^ b[id];
								if(to == par or deleted[to]) continue;

								dfs(dfs, to, v, xor_val ^ c[id]);
							};

							if(append) {
								xor_path.erase(xor_val);
							}
						}; dfs(dfs, to, centroid, c[id]);
					}
					{ // mapping path xors
						std::set<int> xor_path;
						auto dfs = [&](auto&& dfs, int v, int par, int xor_val) -> void {
							bool append = false;
							if(!xor_path.count(xor_val)) {
								map[xor_val] += size[v];

								xor_path.insert(xor_val);
								append = true;
							}

							for(int id: g[v]) {
								int to = v ^ a[id] ^ b[id];
								if(to == par or deleted[to]) continue;

								dfs(dfs, to, v, xor_val ^ c[id]);
							};

							if(append) {
								xor_path.erase(xor_val);
							}
						}; dfs(dfs, to, centroid, c[id]);
					}
				}

				if(loop) answer -= map[0];
				reverse(begin(g[centroid]), end(g[centroid]));
			}

			deleted[centroid] = true;
			for(int id: g[centroid]) {
				int to = centroid ^ a[id] ^ b[id];
				if(deleted[to]) continue;

				solve(solve, to, size[to]);
			}
			deleted[centroid] = false;

		}; solve(solve, start, g.size());

		return answer;
	}
};

int main() {
	int n; scanf("%d", &n);

	solve_t solver(n);
	for(int i = 0; i < n - 1; i++) {
		int u, v, w; scanf("%d%d%d", &u, &v, &w);

		solver.add_edge(u - 1, v - 1, w);
	}
	printf("%lld\n", solver.solve());
}
0