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

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

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


考虑一个约束满足问题的简化版本:假设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;
}
相关文章
|
3月前
|
算法 测试技术 C++
【动态规划】【图论】【C++算法】1575统计所有可行路径
【动态规划】【图论】【C++算法】1575统计所有可行路径
|
4月前
|
算法
飞行员配对方案(Dinic求最大二分图匹配(对匈牙利算法的优化),以及二分图的建图方式)
飞行员配对方案(Dinic求最大二分图匹配(对匈牙利算法的优化),以及二分图的建图方式)
38 0
|
6天前
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
|
5月前
|
机器学习/深度学习 算法
【算法 | 实验7】以最小的步骤收集所有硬币(算法正确性还没想清楚)
题目 最小步骤收集硬币 有许多相邻排列的硬币堆。我们需要以最少的步骤收集所有这些硬币,在一个步骤中,我们可以收集一个水平线的硬币或垂直线的硬币,收集的硬币应该是连续的。 输入描述 输入第一行整数N表示硬币堆的数量
35 0
|
7月前
|
机器学习/深度学习 算法 测试技术
C++算法前缀和的应用:得分最高的最小轮调的原理、源码及测试用例
C++算法前缀和的应用:得分最高的最小轮调的原理、源码及测试用例
|
9月前
|
数据采集 算法 C++
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
DFS(深度优先搜索)详解(概念讲解,图片辅助,例题解释,剪枝技巧)
107 0
|
算法
基于PSO的最优路径优化仿真,带GUI界面,可以设置粒子数目,迭代次数,优化目标,输出最优解和最优路径
基于PSO的最优路径优化仿真,带GUI界面,可以设置粒子数目,迭代次数,优化目标,输出最优解和最优路径
124 0
基于PSO的最优路径优化仿真,带GUI界面,可以设置粒子数目,迭代次数,优化目标,输出最优解和最优路径
|
算法
【算法竞赛进阶指南】程序自动分析(并查集判冲突+离散化)
【算法竞赛进阶指南】程序自动分析(并查集判冲突+离散化)
94 0
|
算法 测试技术
【算法作业】实验三:划分集合-贪心 & 可能的IP地址-回溯
【算法作业】实验三:划分集合-贪心 & 可能的IP地址-回溯
139 0
【算法作业】实验三:划分集合-贪心 & 可能的IP地址-回溯
①特征选取之单变量统计、基于模型选择、迭代选择
特征选取之单变量统计、基于模型选择、迭代选择
263 0
①特征选取之单变量统计、基于模型选择、迭代选择