2115: [Wc2011] Xor(處理環+線性基)

 

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);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章