E - AND-MEX Walk (并查集理解)

49 篇文章 1 订阅
19 篇文章 0 订阅

E - AND-MEX Walk

分析:

  • 结论+并查集的连通性求解

  • 首先易证答案就3种:0,1,2

    故分类讨论(分别对30位求解连通性):

    • 0:存在某一位使得u,v连通
    • 1:存在某一位的连通块的 边的集合 存在偶数边,这样就能先到 偶数边 再到v 这样保证 ans=1
    • 2:其余情况
#include <bits/stdc++.h>
#define int long long 
#define Pa pair<int,int> 
using namespace std;

const int N=2e5+5;
vector <pair<int,int> > g[N+5];
int f[32][N];
int fd(int x,int k){ return f[x][k]==k ? k : f[x][k]=fd(x,f[x][k]); }
int vis[N];
void solve()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        g[u].push_back({v,w});
        g[v].push_back({u,w}) ;
    }
    for(int i=0;i<30;i++) for(int j=1;j<=n;j++) f[i][j]=j;
    for(int i=0;i<30;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x=fd(i,f[i][j]);
            for(auto it : g[j])
            {
                int v=it.first, w=it.second;
                if((w>>i)&1)
                {
                    int y=fd(i,f[i][v]);
                    if(x!=y) f[i][y]=x;
                }
            }
        }
    }
    vector <int> e;
    for(int i=1;i<=n;i++)
    {
        for(auto it : g[i])
        {
            int v=it.first, w=it.second;
            if(w%2==0)
            {
                if(!vis[i]) e.push_back(i);
                if(!vis[v]) e.push_back(v);
                vis[i]=vis[v]=1;
            }
        }
    }
    for(int i=1;i<30;i++)
    {
        vector <int> tp(n+5);
        for(int x : e) tp[fd(i,f[i][x])]=1;
        for(int j=1;j<=n;j++) vis[j]|=tp[fd(i,f[i][j])];
    }
    int q; cin>>q;
    while(q--)
    {
        int u,v; 
        scanf("%lld%lld",&u,&v);
        int fg=0;
        for(int i=0;i<30;i++)
        {
            int x=fd(i,f[i][u]), y=fd(i,f[i][v]);
            if(x==y) {fg=1; break;}
        }   
        if(fg) cout<<"0\n";
        else if(vis[u] ) cout<<"1\n";
        else cout<<"2\n";
    }
}
signed main()
{
    int T=1;
    //cin>>T;
    while(T--) solve();
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值