程序自动分析(并查集加离散化)

简介: 程序自动分析(并查集加离散化)

在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。


考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。


现在给出一些约束满足问题,请分别对它们进行判定。


Input



输入文件的第1行包含1个正整数t,表示需要判定的问题个数。注意这些问题之间是相互独立的。

对于每个问题,包含若干行:


第1行包含1个正整数n,表示该问题中需要被满足的约束条件个数。

接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若e=0,则该约束条件为xi≠xj。


Output



输出文件包括t行。

输出文件的第k行输出一个字符串“YES”或者“NO”(不包含引号,字母全部大写),“YES”表示输入中的第k个问题判定为可以被满足,“NO”表示不可被满足。


Sample Input



2

2

1 2 1

1 2 0

2

1 2 1

2 1 1


Sample Output



NO

YES


HINT



在第一个问题中,约束条件为:x1=x2,x1≠x2。这两个约束条件互相矛盾,因此不可被同时满足。

在第二个问题中,约束条件为:x1=x2,x2=x1。这两个约束条件是等价的,可以被同时满足。

1≤n≤1000000

1≤i,j≤1000000000


思路:



并查集很好做,关键是加上离散化

因为数据规模(1e9)很大,超过了数组的上限。但数据据量(1e6) 开数组是刚刚好的

于是我们通过离散排序去重,只把数之间的关系表示出来即可


C++ lower_bound()函数



lower_bound() 函数用于在指定区域内查找不小于目标值的第一个元素。也就是说,使用该函数在指定范围内查找某个目标值时,最终查找到的不一定是和目标值相等的元素,还可能是比目标值大的元素。


底层代码

int lower_bound(int l,int r,int k){
    while (l < r){
        int mid=l+r >> 1;
        if (a[mid] >= k) r=mid;
        else l=mid+1;
    }
    return l;
}


unique函数



它的功能是元素去重。即”删除”序列中所有相邻的重复元素(只保留一个)。此处的删除,并不是真的删除,而是指重复元素的位置被不重复的元素给占领了。由于它”删除”的是相邻的重复元素,所以在使用unique函数之前,一般都会将目标序列进行排序。


又是一道模板题,听懂了记得给个赞鼓励一下,码字不易,用爱发电。

上ac代码。


有事你就q我;QQ2917366383


学习算法

#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=0;
      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){//!=0 
                f[r1]=r2;  //就是我们的merge操作 
            }
      else if(r1==r2){
                printf("NO\n");
                flag=0;  //如果不满足条件,标记为否 
                break;
            }
        }                  
        if(flag)    printf("YES\n");   //都满足条件了 
    }
    return 0;
}
相关文章
|
机器学习/深度学习 人工智能 算法
时间复杂度O(40n*n)的C++算法:修改图中的边权
时间复杂度O(40n*n)的C++算法:修改图中的边权
|
6月前
|
Shell 网络安全
【错题集-编程题】mari和shiny(动态规划-多源状态线性 dp)
【错题集-编程题】mari和shiny(动态规划-多源状态线性 dp)
|
6月前
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
|
6月前
|
算法 测试技术 C#
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序
|
6月前
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
|
机器学习/深度学习 算法 测试技术
C++算法:有向图计数优化版原理及实现
C++算法:有向图计数优化版原理及实现
|
数据采集 算法 C++
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
1015 0
|
算法 C语言 C++
【模拟】特别数的和、移动距离、连号区间、错误票据思路详解及代码实现
取出最后一位,然后将n除去最后一位,将刚刚取出的进行判定。
80 0
|
算法 搜索推荐 流计算
基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)
基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)
319 0
|
机器学习/深度学习 算法 C++
由数据范围反推算法复杂度以及算法内容
由数据范围反推算法复杂度以及算法内容
下一篇
无影云桌面