# D

# 题目大意

给定 nn 个点 mm 条边的有向图,第 ii 条边从结点 AiA_i 连向结点 BiB_i,权值为 WiW_i
求,从 1n1 \to n 的路径中(可以重复走),路径权值异或的最小值

# 数据范围

  • 2n1032 \le n \le 10^3
  • 0m1030 \le m \le 10^3
  • 0 \le w_i \le 2^

# 题解

# 错解

这个错解,明显忽略了在 a1...ana_1 \oplus ... \oplus a_n 时,并不是 a1...aia_1 \oplus ... \oplus a_i 越小,最终结果也越小的

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int n, m;
vector<PII> g[N];
vector<int> ans;

void dfs(int u) {
for (auto [to, val] : g[u]) {
int t = ans[u] ^ val;

if (ans[to] > t)
ans[to] = t, dfs(to);
}
}

void solve () {
cin >> n >> m, ans = vector<int>(n + 1, 1e18);

for (int i = 1, u, v, w; i <= m; i++)
cin >> u >> v >> w, g[u].push_back({v, w});

ans[1] = 0, dfs(1);

cout << (ans[n] == 1e18 ? -1 : ans[n]) << '\n';
}

# 正解

正解应该是,记录每个点是否遍历过这个状态(异或值,值最大不会超过 210,10242^{10},1024,故可以开数组来记录)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void dfs(int u, int tmp) {
if (u == n)
res = min(res, tmp);

for (auto [to, val] : g[u]) {
int t = tmp ^ val;

if (!st[to][t])
st[to][t] = 1, dfs(to, t);
}
}

void solve () {
cin >> n >> m;

for (int i = 1, u, v, w; i <= m; i++)
cin >> u >> v >> w, g[u].push_back({v, w});

dfs(1, 0);

cout << (res == 1e18 ? -1 : res) << '\n';
}

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

duoxichangan 微信支付

微信支付

duoxichangan 支付宝

支付宝