当サイトの記事にはプロモーションが含まれています。
ABC396 - D - Minimum XOR Path
最終更新:2025-03-22 投稿日:2025-03-22
2025/03/08に行われたAtCoder Beginner Contest 396のD問題の解法についての記事です。
考えたこと
\( 2 \leq N \leq 10 \)なので、頂点\( 1 \)を固定して、\( 2 , ... , N \)に対してnext_permutation
を使っても間に合いそうです。
\( N \)まで到達できれば良いので、道中で辺のラベルのXORを取りつつ、\( N \)に到達できればラベルのXORの最小値を求めていきます。
コードの例
#include <bits/stdc++.h>
using namespace std;
int main() {
int N, M;
cin >> N >> M;
vector<vector<long long>> line(N + 1, vector<long long>(N + 1));
vector<set<int>> lineTo(N + 1);
int u, v;
long long w;
for (int i = 0; i < M; i++) {
cin >> u >> v >> w;
line.at(u).at(v) = w;
line.at(v).at(u) = w;
lineTo.at(u).insert(v);
lineTo.at(v).insert(u);
}
vector<int> A(N - 1);
for (int i = 0; i < N - 1; i++) {
A.at(i) = i + 2;
}
long long ans = -1;
do {
long long ansNow;
int pos = 1;
bool flag = false;
int i = 0;
int nextPos;
while (i < N - 1) {
nextPos = A.at(i);
if (lineTo.at(pos).count(nextPos)) {
if (i == 0) {
ansNow = line.at(pos).at(nextPos);
if (nextPos == N) {
flag = true;
break;
}
}
else {
ansNow = ansNow xor line.at(pos).at(nextPos);
if (nextPos == N) {
flag = true;
break;
}
}
}
else {
break;
}
pos = nextPos;
i++;
}
if (flag) {
if (ans == -1) {
ans = ansNow;
}
else {
ans = min(ans, ansNow);
}
}
} while (next_permutation(A.begin(), A.end()));
cout << ans << endl;
return 0;
}
解法
次の頂点につながる辺があるかどうかはvector<set<int>> lineTo
で管理し、辺の重みはvector<vector<long long>> line
で管理しています。
出発点は頂点\( 1 \)に固定して、c++のnext_permutation
を用いて頂点\( N \)までの辺の重みのXORを取りつつ進んでいきます。頂点\( N \)に到達できればans
の更新を行い、到達できなければ次のnext_permutation
で同様の処理を行います。
頂点\( 2, ... , N \)の順列は\( 9 ! == 362880\)通りなので、最大で9回辺のXORを取ることを考えても十分高速です。
これで回答となります。