洛谷-程序自动分析

题目描述:
在这里插入图片描述
输入格式:
在这里插入图片描述

输出格式:
在这里插入图片描述
输入输出样例:
输入样例1:

2
2
1 2 1
1 2 0
2
1 2 1
2 1 1

输出样例1:

NO
YES

输入样例2:

2
3
1 2 1
2 3 1
3 1 1
4
1 2 1
2 3 1
3 4 1
1 4 0

输出样例2:

YES
NO

思路:
这个题是典型的并查集的题目,我们先处理所有的e=1的情况,将所有的相等的情况并在一起,再处理e=0的时候,当我们出现矛盾(即我们已经将某两个数字并在了一起,但是这两个是不能相等的)时,我们便输出NO,如果整个过程都没有输出NO,则输出YES。
难点:
由于这个题目本身的范围极大,为109大小,加入按照我们常规做法,我们会开一个109大小的数组,这样做会出现MLE,RE等错误提示。 因此我们需要用到离散化的思想做法,将数组排好序,然后利用stl的unique得到我们的实际大小的数组。再进行我们的常规的并查集操作。
技巧:离散化过程
AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
using namespace std;
int t,n,f[1000007],book[1000007*3];  //t表示t组数据,n表示有n个操作,f[]是我们并查集的数字,book[]是离散化的数组 
struct node{
    int x,y,e;
}a[1000001];  
bool cmp(node a,node b){
    return a.e>b.e;
}//排 序将e==1的放在前面 
inline void first(int kkk){
    for(int i=1;i<=kkk;i++)  f[i]=i;
}//初 始 化 
int get(int x){
    if(x==f[x]) return x;
    return f[x]=get(f[x]);
}
int main(){
    scanf("%d",&t);
    while(t--){
      int tot=-1;
      memset(book,0,sizeof(book));
      memset(a,0,sizeof(a));
      memset(f,0,sizeof(f));
    int flag=1;
        scanf("%d",&n);
       
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].e);
            book[++tot]=a[i].x;
            book[++tot]=a[i].y;
        }
        sort(book,book+tot);//排序 
        int reu=unique(book,book+tot)-book;  //去重 
        for(int i=1;i<=n;++i){
           a[i].x=lower_bound(book,book+reu,a[i].x)-book;
           a[i].y=lower_bound(book,book+reu,a[i].y)-book;   
        } 
        first(reu);   //初始化 
        sort(a+1,a+n+1,cmp);  //按e排序 
        for(int i=1;i<=n;i++){
            int r1=get(a[i].x);
            int r2=get(a[i].y);
            if(a[i].e){
                f[r1]=r2;  //就是我们的merge操作 
            }else if(r1==r2){
                printf("NO\n");
                flag=0;  //如果不满足条件,标记为否 
                break;
            }
        }
        if(flag)    printf("YES\n");   //都满足条件了 
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值