• 【LGOJ5651】基础最短路练习题


    你以为这是最短路,其实完全不是最短路

    这题的难点在于对题面这句话的理解:

    "保证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
    ",dis[u]^dis[v]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu
    SSH
    Markdown
    Mac OS 上的一些骚操作
    Linux Bash
    JConsole
    IDEA
    Groovy
    Github
    Git
  • 原文地址:https://www.cnblogs.com/tqr06/p/11854587.html
Copyright © 2020-2023  润新知