Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 5957 Solved: 2545
[Submit][Status][Discuss]
Description
Input
第一行包含兩個整數N和 M, 表示該無向圖中點的數目與邊的數目。 接下來M 行描述 M 條邊,每行三個整數Si,Ti ,Di,表示 Si 與Ti之間存在 一條權值爲 Di的無向邊。 圖中可能有重邊或自環。
Output
僅包含一個整數,表示最大的XOR和(十進制結果),注意輸出後加換行回車。
Sample Input
5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
Sample Output
6
HINT
找了一個線性基的題。發現還是不會做,無奈搜了一波題解
以下圖片來自:https://www.cnblogs.com/ljh2000-jump/p/5869925.html
隨意找一條路徑,然後通過其周圍的環進行異或能否達到最大。由於 環可能很多很多,那麼需要線性基一下,把數據範圍減少。
這裏注意處理環的時候,若u是當前結點,v是其兒子結點,那麼環上所有邊權的異或值是dx[u]^dx[v]^w1。dx[i]是記錄從1開始到i時的所有邊權異或值。這裏是一個新的知識點。。。
AC代碼:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=5e4+10,M=1e5+10;
vector<int>G[M];
int a[N];
bool vis[N];
int n,m;
ll ans,dx[N];
vector<ll>num,val[M];
void dfs(int u,int fa){
vis[u]=1;
for(int i=0;i<G[u].size();++i){
int v=G[u][i];
ll w1=val[u][i];
if(v==fa) continue;
if(vis[v]){
num.pb(dx[u]^dx[v]^w1);
continue;
}
dx[v]=dx[u]^w1;
dfs(v,u);
}
}
ll p[100];
void insert(ll x){
for(int j=62;j>=0;j--) {
if(!(x>>j)) continue;
if(!p[j]) { p[j]=x; return ; }
x^=p[j];
}
}
int main(){
cin>>n>>m;
rep(i,1,m){
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
G[u].pb(v);
G[v].pb(u);
val[u].pb(w);
val[v].pb(w);
}
dfs(1,0);
for(int i=0;i<num.size();++i){
insert(num[i]);
}
ans=dx[n];
for(int i=62;i>=0;--i){
if((ans^p[i])>ans) ans=ans^p[i];
}
printf("%lld\n",ans);
}