洛谷11月月赛 III Div.2 T2 基础最短路练习题

题目大意:

给定n个点m条边的无向简单联通图G,边有边权。保证没有重边和自环。

定义一条简单路径的权值为路径上所有边边权的异或和。

保证G中不存在简单环使得边权异或和不为00。

Q次询问x到y的最短简单路径。

解题思路:

我是跑了遍SPFA 每次查询的答案就是dis[x] xor dis[y]
要卡SPFA的话会T但是没卡
我们可以dfs一遍求出每个点到1的距离然后O(1)查询

Accepted code:Accepted\ code:

#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]);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章