bzoj - 2115 Xor —— 線性基
阿新 • • 發佈:2018-11-12
題意:
求圖中從1點到n點的所有路徑中邊權值異或的最大值
思路:
首先要理解,路徑可以任意異或環
像圖中,從1到n的黑色路徑,可以由任意一條紅色路徑到一個環,走遍環之後,再通過紅色路徑回到黑色路徑上,這時紅色路徑上的值被異或了兩次為0,結果就相當於是黑色路徑異或藍色環
環是沒有大小限制的,甚至可以包括黑色路徑,所以通過這種方法可以由任意一條從1到n的路徑得到所有的路徑
剩下的問題一個是求所有環的異或值,可以由一遍深搜得到,每次搜尋下一個點時,若這個點被訪問過,就會形成一個環
另一個問題是求出所有環之後怎麼得到最大的異或值,即從環的異或值中選擇一些數使這些數異或起來最大,線性基
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <cstring> #include <algorithm> using namespace std; #define ll long long #define max_ 200100 #define mod 1000000007 #define inf 0x3f3f3f3f struct node { int to; ll w; }zz; vector< vector<struct node> >v; int n,m; ll p[70]; ll value[10000000]; int pl=0; bool vis[50010]; ll dis[50010]; void dfs(int u) { for(int i=0;i<v[u].size();i++) { int to=v[u][i].to; if(vis[to]) { value[++pl]=dis[u]^dis[to]^v[u][i].w; } else { vis[to]=true; dis[to]=dis[u]^v[u][i].w; dfs(to); } } } void insert(ll n) { for(int i=62;i>=0;i--) { if((n>>i)&1) { if(p[i]) { n=n^p[i]; } else { p[i]=n; break; } } } } int main(int argc, char const *argv[]) { scanf("%d%d",&n,&m); v.resize(n+1); for(int i=1;i<=m;i++) { int x,y; ll w; scanf("%d%d%lld",&x,&y,&w); if(x!=y) { zz.w=w; zz.to=x; v[y].push_back(zz); zz.to=y; v[x].push_back(zz); } } dfs(1); for(int i=1;i<=pl;i++) { insert(value[i]); } ll ans=dis[n]; for(int i=62;i>=0;i--) { if((ans^p[i])>ans) { ans=ans^p[i]; } } printf("%lld\n",ans ); return 0; }