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