結果
| 問題 | No.1602 With Animals into Institute 2 | 
| コンテスト | |
| ユーザー |  | 
| 提出日時 | 2025-06-30 01:19:52 | 
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 401 ms / 4,000 ms | 
| コード長 | 4,203 bytes | 
| コンパイル時間 | 3,373 ms | 
| コンパイル使用メモリ | 294,408 KB | 
| 実行使用メモリ | 40,412 KB | 
| 最終ジャッジ日時 | 2025-06-30 01:20:05 | 
| 合計ジャッジ時間 | 10,665 ms | 
| ジャッジサーバーID (参考情報) | judge4 / judge2 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 3 | 
| other | AC * 36 | 
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll inf = 1e18;
namespace cplib {
	template <class Monoid>
	struct shortest_non_zero_path {
		template <class U>
		using pqmin = priority_queue<U, vector<U>, greater<U>>;
		struct edge {
			int to;
			ll cost;
			typename Monoid::value_type x;
			int id;
			bool is_consistent;
		};
		int n, m;
		vector<vector<edge>> g;
		shortest_non_zero_path() {}
		shortest_non_zero_path(int n) : n(n), m(0), g(n) {}
		inline void add_edge(int u, int v, ll c, typename Monoid::value_type x) {
			g[u].push_back({v, c, x, m});
			g[v].push_back({u, c, Monoid::inv(x), m});
			m++;
		}
		vector<ll> solve(int s) {
			// step0: 最短路木の作成
			vector<ll> dist_T(n, inf);
			vector<int> depth_T(n, -1);
			vector<int> pred_T(n, -1);
			vector<typename Monoid::value_type> label_T(n, Monoid::e());
			pqmin<pair<ll, int>> pq_T;
			dist_T[s] = 0, depth_T[s] = 0, label_T[s] = Monoid::e();
			pq_T.push({dist_T[s], s});
			while (pq_T.size()) {
				auto [d, p] = pq_T.top();
				pq_T.pop();
				if (dist_T[p] < d) continue;
				for (auto&& e : g[p]) {
					if (dist_T[e.to] > dist_T[p] + e.cost) {
						dist_T[e.to] = dist_T[p] + e.cost;
						depth_T[e.to] = depth_T[p] + 1;
						pred_T[e.to] = p;
						label_T[e.to] = Monoid::op(label_T[p], e.x);
						pq_T.push({dist_T[e.to], e.to});
					}
				}
			}
			// step1: q(v), uf の初期化
			vector<ll> q(n, inf);
			vector<int> par(n, -1);
			auto root = [&](auto root, int x) -> int {
				if (par[x] == -1) return x;
				return par[x] = root(root, par[x]);
			};
			auto merge = [&](int p, int c) -> void {
				par[c] = p;
			};
			// step2: 非整合な e を列挙
			vector<ll> h(m, inf);
			vector<int> u(m), v(m);
			pqmin<pair<ll, int>> pq_F;
			for (int i = 0; i < n; i++) {
				for (auto&& e : g[i]) {
					e.is_consistent = (Monoid::op(label_T[i], e.x) == label_T[e.to]);
					u[e.id] = i, v[e.id] = e.to;
					if (!e.is_consistent) {
						h[e.id] = dist_T[i] + dist_T[e.to] + e.cost;
						pq_F.push({h[e.id], e.id});
					}
				}
			}
			// step3: h が空になるまで実行する
			while (pq_F.size()) {
				// step3.1: pq_F から最小の h(e) なる e を取り、w1,w2 を計算
				auto [he, e] = pq_F.top();
				pq_F.pop();
				if (h[e] != he) continue;
				int w1 = root(root, u[e]);
				int w2 = root(root, v[e]);
				// step3.2: B に wi を加え、unionfind の更新
				vector<int> B;
				while (w1 != w2) {
					if (depth_T[w1] < depth_T[w2]) swap(w1, w2);
					B.push_back(w1);
					w1 = root(root, pred_T[w1]);
				}
				// step3.3: w\in B について処理
				for (auto&& w : B) {
					merge(w1, w);
					q[w] = he - dist_T[w];
					for (auto&& f : g[w]) {
						if (f.is_consistent) {
							if (h[f.id] > q[w] + dist_T[f.to] + f.cost) {
								h[f.id] = q[w] + dist_T[f.to] + f.cost;
								pq_F.push({h[f.id], f.id});
							}
						}
					}
				}
			}
			// step4 : 最短路木で満たしている場合の更新
			for (int i = 0; i < n; i++) {
				if (label_T[i] != Monoid::e()) {
					q[i] = min(q[i], dist_T[i]);
				}
			}
			// step5 : 結果を返す
			return q;
		}
	};
	/*
	Shortest Non Zero Path
	ref :
	- https://arxiv.org/abs/1906.04062
	- https://gist.github.com/wata-orz/d3037bd0b919c76dd9ddc0379e1e3192
	*/
}  // namespace cplib
struct Monoid_Xor {
	using value_type = ll;
	ll x;
	static ll op(ll x, ll y) {
		return x ^ y;
	}
	static ll inv(ll x) {
		return x;
	}
	static ll e() {
		return 0;
	}
	static constexpr bool commute = true;
};
ll op(ll a, ll b) {
	return a ^ b;
}
ll id() {
	return 0;
}
ll inv(ll x) {
	return x;
}
int main() {
	cin.tie(nullptr)->sync_with_stdio(false);
	int N, M, K;
	cin >> N >> M >> K;
	vector<int> A(M), B(M), C(M), X(M);
	for (int i = 0; i < M; i++) {
		cin >> A[i] >> B[i] >> C[i];
		A[i]--, B[i]--;
		string s;
		cin >> s;
		for (auto&& e : s) X[i] = 2 * X[i] + (e - '0');
	}
	cplib::shortest_non_zero_path<Monoid_Xor> solver(N);
	for (int i = 0; i < M; i++) {
		solver.add_edge(A[i], B[i], C[i], X[i]);
	}
	auto d = solver.solve(N - 1);
	for (int i = 0; i < N - 1; i++) {
		if (d[i] == inf)
			cout << -1 << "\n";
		else
			cout << d[i] << "\n";
	}
}
            
            
            
        