题解:P9565 [SDCPC 2023] Not Another Path Query Problem

P9565 题解

题面

原题传送门

思路

我们先设一个路径的与和为 val

首先我们要知道按位与的操作从二进制下的每一位来看,最终的结果为 1 的要求为路径上边的权值在这一位都为 1,然后既然在得到这个结果的过程按二进制拆开,那么我们比大小也按二进制下来比较。

那么对于两个数 a,b,若 a>b,则有两种情况:

  1. a 的最高位比 b 高,如 a=8,b=410010
  2. a 的前几位和 b 一样,在第一个不一样的位置 a1b0,如 a=5,b=4101100

于是接下来就可以考虑这道题的做法了。

我们就是考虑从大到小枚举路径的与和,并设置一个数 num,设当前枚举的是 2k,如果 V 的第 k 位为 1,则令 numnum+2k,否则就将所有满足 wi&num=num 的边取出来,用一个并查集维护一下,然后一个个询问遍历过去,如果两个点联通,那么这个询问就输出 Yes,最后在判断 wi&V=V 的边是否满足每一个询问。

于是就有人问了,为什么 V 的第 k 位为 1,就令 numnum+2k,其实很简单,因为如果到当前部分询问还是 No,那么就说明目前得保证路径的 val 大于等于 V,那么就得保证 valV 的前几位相等,于是这个做法的正确性就是对的啦。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=5e5+5;
ll n,m,k,v,fa[MN],sz[MN],ans[MN],num;
struct edge{ll u,v,w;}e[MN];
struct question{ll u,v;}q[MN];
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
ll find(ll x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(ll x, ll y){
    x=find(x);y=find(y);
    if(x==y) return;
    if(sz[x]>sz[y]) swap(x,y);
    fa[x]=y;sz[y]+=sz[x];
}
int main(){
    n=read();m=read();k=read();v=read();
    for(int i=1; i<=m; i++) e[i].u=read(),e[i].v=read(),e[i].w=read();
    for(int i=1; i<=k; i++) q[i].u=read(),q[i].v=read();
    for(int i=1; i<=n; i++) fa[i]=i,sz[i]=1;
    for(int i=1; i<=m; i++) if((e[i].w&v)==v) merge(e[i].u,e[i].v);
    for(int i=1; i<=k; i++) if(find(q[i].u)==find(q[i].v)) ans[i]=1;
    for(int i=63; ~i; i--){
        num|=(1ll<<i);
        if(!((v>>i)&1)){
            for(int i=1; i<=n; i++) fa[i]=i,sz[i]=1;
            for(int i=1; i<=m; i++) if((e[i].w&num)==num) merge(e[i].u,e[i].v);
            for(int i=1; i<=k; i++) if(find(q[i].u)==find(q[i].v)) ans[i]=1;
            num^=(1ll<<i);
        }
    }
    for(int i=1; i<=k; i++) if(ans[i]) printf("Yes\n");else printf("No\n");
    return 0;
}
posted @   naroto2022  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
战斗是残酷的,无法做出多余的考虑!