• 2017乌鲁木齐区域赛I(带权并查集)


    #include<bits/stdc++.h>
    using namespace std;
    int f[200010];//代表元
    long long rl[200010];//记rl[i]为结点i到根的路径上所有边的亦或和(这里可以忽视 x(0)的情况)
    void init(int n)
    {
        for(int i=1;i<=n;i++)
            f[i]=i,rl[i]=0;//初始化
    }
    int fd(int x)//并查集模板
    {
        if(f[x]==x)
            return x;
        int fa=f[x];
        f[x]=fd(f[x]);
        rl[x]=rl[x]^rl[fa];//由于x更换了代表元,换的路径要算上
        return f[x];
    }
    int join(int x,int y,long long val)
    {
        int fx=fd(x),fy=fd(y);
        if(fx==fy)
            return 0;
        f[fx]=fy;
        rl[fx]=rl[fx]^rl[x]^rl[y]^val;//同一个集合(代表元为 c)
    //内两个元素 a 和 b 的亦或值为 x(a) xor x(b) = (x(a) xor x(c)) xor (x(b) xor x(c))。
        return 1;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,c;
            scanf("%d%d",&n,&c);
            int x,y;
            for(int i=1;i<n;i++)
                scanf("%d%d",&x,&y);
            init(n);
            int xx,yy;
            long long val;
            int ans=c;
            for(int i=1;i<=c;i++)
            {
                scanf("%d%d%lld",&xx,&yy,&val);
                if(ans!=c)
                    continue;
                if(!join(xx,yy,val)&&(rl[xx]^rl[yy])!=val)//当某一条信息中两点xx与yy在同一连通块上,
                //那么就必须满足xx与yy各自代表元异或的值等于val,否则就停止,只能满足之前的要求数量。
                    ans=i-1;
            }
            printf("%d ",ans);
        }
        return 0;
    }
    //带权并查集可以考虑模板,根据实际问题修改里面的变量

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    计算机病毒的认识
    计算机病毒的认识
    围棋知多少
    围棋知多少
    工业相机基础知识(一)
    辨异 —— 逻辑之辨、人文社科观念
    辨异 —— 逻辑之辨、人文社科观念
    telnet 的使用(ping 与 telnet)
    HDU 2437 Jerboas (剪枝搜索)
    设计模式
  • 原文地址:https://www.cnblogs.com/ldudxy/p/9519979.html
Copyright © 2020-2023  润新知