【bzoj2115】[Wc2011] Xor(線性基)

這道題差不多是一道線性基的模板題。

如圖,我們首先找到一條1到n的路徑,這裏是1-4-6。

然後考慮加入的環。

當加入的環在這個路徑上時,例如加入環1-2-4-1,如圖:

這個時候我們發現,我們加入這個環之後,我們的路徑就變成了1-2-4-6,這條路徑的異或和就等於原路徑的異或和再異或這個環的所有邊的異或和。

當加入的環不在原路徑上時,例如加入環2-3-5-2,如圖:

我們會發現加入這個環的時候,從原路徑到這個環的這一條路徑走了兩次,所以可以不計,所以加入這個環之後的異或和還是等於原路徑的異或和再異或這個環的所有邊的異或和。

所以我們就可以找到一條路徑,然後把所有的其它的環加入到線性基裏,然後就可以求出答案了,具體請看代碼。

如果有誤在評論區吼一聲哦!

#include<cstdio>
#include<cctype>
#include<cstring>
long long a[65],d[50010],val[200010];
int n,m,tot,vis[50010],head[50010],nxt[200010],to[200010];
int rdint(){
	int x=0;
	char c;
	do c=getchar();
	while(!isdigit(c));
	do{
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}while(isdigit(c));
	return x;
}
long long rdll(){
	long long x=0;
	char c;
	do c=getchar();
	while(!isdigit(c));
	do{
		x=(x<<1ll)+(x<<3ll)+(c^48);
		c=getchar();
	}while(isdigit(c));
	return x;
}
void add_edge(int u,int v,long long w){
	nxt[++tot]=head[u];
	to[tot]=v;
	val[tot]=w;
	head[u]=tot;
	return;
}
void insert(long long x){
	for(int i=61;i>=0;i--)
		if(x&(1ll<<i)){
			if(!a[i]){
				a[i]=x;
				break;
			}
			x^=a[i];
			if(!x)
				break;
		}
	return;
}
long long getmax(long long ret){
	for(int i=61;i>=0;i--)
		if(!(ret&(1ll<<i)))
			ret^=a[i];
	return ret;
}
void dfs(int u,int fa){
	vis[u]=1;
	for(int i=head[u];~i;i=nxt[i]){
		int v=to[i];
		long long w=val[i];
		if(v==fa)
			continue;
		if(vis[v])
			insert(d[u]^d[v]^w);
		else{
			d[v]=d[u]^w;
			dfs(v,u);
		}
	}
	return;
}
int main(){
	memset(head,-1,sizeof(head));
	n=rdint();
	m=rdint();
	for(int i=1;i<=m;i++){
		int u=rdint(),v=rdint();
		long long w=rdll();
		add_edge(u,v,w);
		add_edge(v,u,w);
	}
	dfs(1,-1);
	printf("%lld",getmax(d[n]));
	return 0;
}

 

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