zoukankan      html  css  js  c++  java
  • 判断好朋友(并查集离线操作+离散化)

    链接:https://ac.nowcoder.com/acm/contest/5158/H
    来源:牛客网

    牛可乐作为三军统帅,是要时时刻刻关照着下属的。

    现在牛可乐想要知道自己的手下之间的友好关系,所以他收集了 n 张纸条,上面写着三个整数 ai,bi,ci,表示如果 ci 为 1,表示手下 ai 和手下 bi是朋友,反之则是敌人。

    牛可乐想要知道这些信息有没有互相矛盾的地方,可是这个问题太难了,只好来问你了

    如果 A 与 B 友好,又与 友好,那么 与 也是友好的。

    如果两个人既是友好的又是不友好的则视为相互矛盾的。
    牛可乐的手下有 1e9 个。

    输入描述:

    输入第一行给出一个正整数 T,表示测试案例的数量。

    对于每个测试用例.第一行给出一个正整数 n,表示有 n 个友好关系

    接下来每 nnn 行给出三个正整数 ai,bi,ci,表示手下 ai 和手下 bi之间的友好关系.

    输出描述:

    每组案例输出一行,若这些关系没有矛盾,输出  "YES”,否则输出 “NO”

    链接:https://ac.nowcoder.com/acm/contest/5158/H
    来源:牛客网

    输入

    复制 
    2
    3
    1 2 1
    1 3 1
    2 3 1
    3
    1 2 1
    1 3 1
    2 3 0

    输出

    复制 
    YES
    NO

    备注:

    1≤T≤10
    1≤n≤1e6
    1≤a,b≤1e9
    c∈{0,1}
    对于每组样例,保证 ∑n≤1010000
    建议使用 scanf 读入
    一眼看过去肯定要用并查集的
    1.但是a,b是小于等于1e9的所以要进行离散化,因为n是小于1e6的
    2.要判断是不是有矛盾,你可以先加入ci==1的就是先让朋友连成一个并查集,然后在判断ci==0的两个节点是不是连在了一起(是不是
    朋友)

     这是关键:

    for(int i=1;i<=n;i++){
                if(a[i].ci==1){
                    marge(a[i].ai,a[i].bi);
                }
            }
            for(int i=1;i<=n;i++){
                if(a[i].ci==0){
                    int u=find(a[i].ai);
                    int v=find(a[i].bi);
                    if(v==u){
                        flag=0;
                        break;
                    }
                }
            }
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=5e6+1000;
    struct node{
        int ai;
        int bi;
        int ci;
    }a[maxn];
    bool cmp(node x,node y){
        return x.ci>y.ci;
    } 
    int pre[maxn];
    int id[maxn];
    int r[maxn]; 
    int cnt=0;
    int n;
    void inint(){
        sort(id+1,id+1+cnt);
        cnt=unique(id+1,id+1+cnt)-(id);
        for(int i=1;i<=n;i++){
            a[i].ai=lower_bound(id+1,id+1+cnt,a[i].ai)-(id);
            a[i].bi=lower_bound(id+1,id+1+cnt,a[i].bi)-(id);
        }
    } 
    int find(int x){
        if(pre[x]==x){
            return x;
        }
        else{
            pre[x]=find(pre[x]);
            return pre[x]; 
        }
    }
    void marge(int x,int y){
        int t1=find(x);
        int t2=find(y);
        if(t1==t2){
            return ;
        } 
        if(r[t2]>r[t1]){
            pre[t1]=t2;
            r[t2]+=r[t1];
        }
        else{
            pre[t2]=t1;
            r[t1]+=r[t2];
        }
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            cnt=0;
            for(int i=1;i<=n;i++){
                scanf("%d%d%d",&a[i].ai,&a[i].bi,&a[i].ci);
                id[++cnt]=a[i].ai;
                id[++cnt]=a[i].bi;
            }
            inint();//离散化
            for(int i=0;i<=cnt;i++){
                pre[i]=i;
                r[i]=1;
            } 
            int flag=1;
            for(int i=1;i<=n;i++){
                if(a[i].ci==1){
                    marge(a[i].ai,a[i].bi);
                }
            }
            for(int i=1;i<=n;i++){
                if(a[i].ci==0){
                    int u=find(a[i].ai);
                    int v=find(a[i].bi);
                    if(v==u){
                        flag=0;
                        break;
                    }
                }
            }
            if(flag){
                printf("YES
    ");
            } 
            else{
                printf("NO
    ");
            }
        }
    } 
    /*
    2
    3
    1 2 1
    1 5 1
    2 5 1
    */ 
  • 相关阅读:
    c# 发送邮件笔记(一)
    windows API(一)
    SubSonic3.0安装
    Node.js安装MongoDB驱动
    JDBC连接数据库方法
    Delphi LiveBindings如何绑定一个对象(二)(转)
    delphi RTTI机制学习(一)
    Delphi LiveBinds组件
    mysql 每个分类各取5条
    mysql in(...) 1次取出当前记录及上1条下1条记录, 且使用了主键作为索引
  • 原文地址:https://www.cnblogs.com/lipu123/p/14170873.html
Copyright © 2011-2022 走看看