……

解题报告: luogu P3907

题目链接:P3907 圈的异或

sb 题,但还是没做出来。

核心思想是 \(dfs\) 对于不是继承节点的已经扫过的点如果被连接就形成环。

异或可以用前缀和来处理。

借助一个定理:

\[a \;\text{xor}\; b\; \text{xor}\; b=a \]

直接把前面的再异或掉即可。

然而不过样例。

?????

因为可能有自环,更恐怖的是 \(dfs\) 起点的自环。

怎么处理呢?

方法一:特判。
不多说了。

方法二:起始 \(dfs\) 的父节点不是自己就好了,比如说 \(n+1\)\(-1\)\(0\) 之类的。

复杂的应该是 \(\mathcal O(T(n+m))\)

\(Code:\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

#define read(x) scanf("%d",&x)
#define MAXN 55

struct node
{
	int to,nxt,w;
}e[MAXN<<1];
int head[MAXN],cnt=0;
int T,n,m,x,y,c;
int sum[MAXN],vis[MAXN];
bool ans=true;

void add(int u,int v,int z)
{
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	e[cnt].w=z;
	head[u]=cnt;
	return;
}

void clear()
{
	memset(e,0,sizeof(e)),memset(head,0,sizeof(head)),cnt=0;
	memset(sum,0,sizeof(sum)),memset(vis,0,sizeof(vis));
	ans=true;
	return;	
}

void dfs(int cur,int fa)
{
	vis[cur]=1;
	for(int i=head[cur];i;i=e[i].nxt)
	{
		int j=e[i].to;
		if(j==fa) continue;
		if(!vis[j]) sum[j]=sum[cur]^e[i].w,dfs(j,cur);
		else
		{
			int now=sum[cur]^sum[j]^e[i].w;
			if(now){ans=false;return;}
		}
	}
	return;
}

int main()
{
	read(T);
	while(T--)
	{
		clear();
		read(n),read(m);
		for(int i=1;i<=m;i++)
		{
			read(x),read(y),read(c);
			add(x,y,c);
			add(y,x,c);
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				dfs(i,0);
				if(!ans){puts("No");break;}
			}
		}
		if(ans) puts("Yes");
	}
	return ~~0;
}
posted @ 2020-05-19 10:06  童话镇里的星河  阅读(135)  评论(0编辑  收藏  举报