题目大意:
给定n个点m条边的无向简单联通图G,边有边权。保证没有重边和自环。
定义一条简单路径的权值为路径上所有边边权的异或和。
保证G中不存在简单环使得边权异或和不为00。
Q次询问x到y的最短简单路径。
解题思路:
我是跑了遍SPFA 每次查询的答案就是dis[x] xor dis[y]
要卡SPFA的话会T但是没卡
我们可以dfs一遍求出每个点到1的距离然后O(1)查询
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100005;
struct Line {
int to, w, next;
}e[N<<2];
int n, m, q, cnt;
int vis[N], dis[N], last[N];
inline void add(int x, int y, int w) {
e[++cnt] = (Line){y, w, last[x]}; last[x] = cnt;
}
void spfa() { //把这里换成dfs就是O(n + m)(SPFA真香)
memset(vis, 0, sizeof vis);
for (int i = 1; i <= n; ++i) dis[i] = 1 << 30;
queue <int> q; q.push(1);
dis[1] = 0, vis[1] = 1;
while (q.size()) {
int u = q.front(); q.pop(), vis[u] = 0;
for (int i = last[u]; i; i = e[i].next) {
int v = e[i].to;
if (dis[v] > (dis[u] ^ e[i].w)) {
dis[v] = dis[u] ^ e[i].w;
if (!vis[v])
q.push(v), vis[v] = 1;
}
}
}
}
int main() {
scanf("%d %d %d", &n, &m, &q);
for (int i = 1, x, y, w; i <= m; ++i)
scanf("%d %d %d", &x, &y, &w),
add(x, y, w), add(y, x, w);
spfa();
while (q--) {
int x, y;
scanf("%d %d", &x, &y);
printf("%d\n", dis[x] ^ dis[y]);
}
}