Educational Codeforces Round 27
D
模拟
E
扫描线板子
G
题意
给你一个无向带权图,定义最短路为一条路径上各条边的权值异或,求从点1到点N的最短路径
分析
考虑整张无向图,造成answer行成差异的有:路径不一样,但最后都能到达n,说明一定行成了环,有可能是多走了一些环上的边,或者走了环的子集,但还可以走剩下的一部分,
所以问题转化为,如何解决环上xor对answer最优,这便可以用线性基了
直接dfs整张图,求出任意一个1到n,dfs过程中将环的xor值扔到线性基里,最后在去个min即可
!!!trick : 最后从线性基中取min时, 要从高位到低位xor , 这样才是最优的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5 + 10; vector<pair<int,int> >G[maxn]; int dis[maxn]; bool vis[maxn]; int loops[maxn]; int a[70]; int ls; int n,m; int u, v, w; void dfs(int now, int s) { vis[now]=1, dis[now]=s; int len = G[now].size(); for(int i = 0; i < len; i++) { int v=G[now][i].first; int w=G[now][i].second; if(!vis[v]) dfs(v,s^w); else loops[++ls]=s^dis[v]^w; } } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } dfs(1 ,0); int answer = dis[n]; for(int i = 1; i <= ls; i++) { for(int j = 31; j>=0; j--) { if((loops[i]>>j)&1) { if(!a[j]) {a[j]=loops[i];break;} else loops[i]^=a[j]; } } } for(int i = 31; i >= 0; i--) ///!!!!高到低 { answer=min(answer, answer^a[i]); } printf("%d\n", answer); return 0; }
要么优秀要么生锈