2115: [Wc2011] Xor
分析:
对于图中的一个环,是可以从1到这个环,转一圈然后在回到1的,所以可以一开始走很多个环,然后在走一条1到n的路径。
那么可以求出所有的环,加入到线性基中,然后任意一条1->n的路径,取一遍最大值。
如果1->n的路径就是最终要走的路径,那么就取到了。如果不是,这我们走的这条路径是p1,最终答案最大的路径是p2,那么p1和p2合起来就是个环,如果p2更优和这个环异或,就把p1消掉了。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 50005; struct Edge{ int to, nxt; LL w; } e[N * 4]; int head[N], En; LL dis[N], b[N]; bool vis[N]; vector<LL> cir; inline void add_edge(int u,int v,LL w) { ++En; e[En].to = v, e[En].w = w, e[En].nxt = head[u]; head[u] = En; } void dfs(int u) { vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (vis[v]) { cir.push_back(dis[u] ^ e[i].w ^ dis[v]); } else { dis[v] = dis[u] ^ e[i].w; dfs(v); } } } void Insert(LL x) { for (int i = 60; ~i; --i) if ((x >> i) & 1) { if (b[i]) x ^= b[i]; else { b[i] = x; break; } } } int main() { int n = read(), m = read(); for (int i = 1; i <= m; ++i) { int u = read(), v = read(); LL w = read(); add_edge(u, v, w); } dfs(1); for (int i = 0; i < (int)cir.size(); ++i) Insert(cir[i]); LL ans = dis[n]; for (int i = 60; ~i; --i) if (ans < (ans ^ b[i])) ans = ans ^ b[i]; cout << ans; return 0; }