你以为这是最短路,其实完全不是最短路
这题的难点在于对题面这句话的理解:
"保证G中不存在简单环使得边权异或和不为0"
意思是,图里面出现的环,其上的权值异或和一定为0
思考一下这样的环有什么特点呢?
无论在这个环上怎么走,走一边和另一边的答案一定是相同的!
因为两个相同的数异或为0,即这个环的两边的边权是一样的
所以我们只需要在图上随便跑出一棵树,直接输出两个点之间的路径异或值即可
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 500005
using namespace std;
int n,m,q,u,v;
ll w;
struct Edge
{
int next,to;
ll dis;
}edge[N<<1];
int cnt=0,head[N];
inline void add_edge(int from,int to,ll dis)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
head[from]=cnt;
}
int dep[N];
ll dis[N];
void dfs(int u,int fa)
{
for(register int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa) continue;
if(dep[v]!=0x3f3f3f3f) continue;
dep[v]=dep[u]+1;
dis[v]=dis[u]^edge[i].dis;
dfs(v,u);
}
}
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
int main()
{
read(n);read(m);read(q);
for(register int i=1;i<=m;++i)
{
read(u);read(v);read(w);
add_edge(u,v,w);
add_edge(v,u,w);
}
memset(dep,0x3f,sizeof(dep));
dep[1]=0;
dfs(1,0);
while(q--)
{
read(u);read(v);
printf("%lld\n",dis[u]^dis[v]);
}
return 0;
}
原文地址:https://www.cnblogs.com/tqr06/p/11854587.html
时间: 2024-10-10 00:57:17