結果

問題 No.1769 Don't Stop the Game
ユーザー polylogKpolylogK
提出日時 2021-10-29 19:58:47
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 3,827 bytes
コンパイル時間 1,158 ms
コンパイル使用メモリ 88,024 KB
実行使用メモリ 30,388 KB
最終ジャッジ日時 2024-06-29 17:53:28
合計ジャッジ時間 39,095 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
10,752 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 4 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 5 ms
5,376 KB
testcase_06 AC 4 ms
5,376 KB
testcase_07 AC 6 ms
5,376 KB
testcase_08 AC 1,835 ms
14,476 KB
testcase_09 AC 1,522 ms
12,240 KB
testcase_10 AC 2,420 ms
19,604 KB
testcase_11 AC 1,248 ms
11,368 KB
testcase_12 AC 1,127 ms
16,980 KB
testcase_13 AC 1,226 ms
17,220 KB
testcase_14 AC 1,429 ms
17,244 KB
testcase_15 AC 1,895 ms
17,336 KB
testcase_16 AC 2,388 ms
17,340 KB
testcase_17 AC 2,993 ms
19,392 KB
testcase_18 TLE -
testcase_19 TLE -
testcase_20 TLE -
testcase_21 TLE -
testcase_22 TLE -
testcase_23 AC 776 ms
17,300 KB
testcase_24 AC 916 ms
17,336 KB
testcase_25 AC 144 ms
17,844 KB
testcase_26 AC 438 ms
30,388 KB
testcase_27 AC 1,142 ms
26,404 KB
testcase_28 TLE -
testcase_29 -- -
testcase_30 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

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

#define NDEBUG

using i64 = long long;

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);

		std::vector<bool> deleted(g.size());
		auto solve = [&](auto&& solve, int root) -> void {
			static std::vector<int> size(g.size());
			auto calc_size = [&](auto&& dfs, int v, int par) -> int {
				size[v] = 1;
				for(int id: g[v]) {
					int to = v ^ a[id] ^ b[id];
					if(to == par or deleted[to]) continue;

					size[v] += dfs(dfs, to, v);
				}
				return size[v];
			}; calc_size(calc_size, root, -1);

			auto get_centroid = [&](auto&& dfs, int v, int par) -> int {
				for(int id: g[v]) {
					int to = v ^ a[id] ^ b[id];
					if(to == par or deleted[to]) continue;

					if(size[to] > size[root] / 2) return dfs(dfs, to, v);
				}
				return v;
			};
			int centroid = get_centroid(get_centroid, root, -1);

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

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

			calc_size(calc_size, centroid, -1);

			#ifndef NDEBUG
			printf("root: %d\n", root + 1);
			printf("centroid: %d\n", centroid + 1);
			for(auto e: deleted) printf("%d ", (int)e); puts("");
			for(auto e: size) printf("%d ", e); puts("");
			for(int id: g[centroid]) if(!deleted[a[id] ^ b[id] ^ centroid])
				printf("%d ", (a[id] ^ b[id] ^ centroid) + 1); puts("");
			#endif

			// [u-centroid-v]
			for(int loop = 0; loop < 2; loop++) {
				std::map<int, i64> 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]);
					}
				}

				#ifndef NDEBUG
				printf("loop(%d): ", loop);
				for(auto [p, q]: map) printf("(%d: %lld), ", p, q); puts("");
				printf("%lld\n", answer);
				#endif

				reverse(begin(g[centroid]), end(g[centroid]));
				if(loop) answer -= map[0];
			}
			#ifndef NDEBUG
			puts("");
			#endif
		}; solve(solve, start);

		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