ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

并查集的应用 + 离散化:程序自动分析

2021-07-15 16:04:12  阅读:184  来源: 互联网

标签:约束条件 相等 int 查集 离散 满足 自动 x2 x3


题目链接:https://www.luogu.com.cn/problem/P1955

 题目:

题目描述

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

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

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

输入格式

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

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

第一行包含一个正整数 nn,表示该问题中需要被满足的约束条件个数。接下来 nn 行,每行包括三个整数 i,j,ei,j,e,描述一个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 e=1e=1,则该约束条件为 x_i=x_jxi​=xj​。若e=0e=0,则该约束条件为 x_i\neq x_jxi​=xj​。

输出格式

输出包括 tt 行。

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

输入输出样例

输入 #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

说明/提示

【样例解释1】

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

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

【样例说明2】

在第一个问题中,约束条件有三个:x_1=x_2,x_2= x_3,x_3=x_1x1​=x2​,x2​=x3​,x3​=x1​。只需赋值使得 x_1=x_2=x_3x1​=x2​=x3​,即可同时满足所有的约束条件。

在第二个问题中,约束条件有四个:x_1=x_2,x_2= x_3,x_3=x_4,x_4\neq x_1x1​=x2​,x2​=x3​,x3​=x4​,x4​=x1​。由前三个约束条件可以推出 x_1=x_2=x_3=x_4x1​=x2​=x3​=x4​,然而最后一个约束条件却要求 x_1\neq x_4x1​=x4​,因此不可被满足。

【数据范围】

注:实际上 n\le 10^6n≤106 。

 思路:

1.离散化

1.首先,此题的数据范围i,j很大,1e9的范围, 而n的范围 <= 1e6,每个n对应两个点,所以总共使用到的数据不会超过 2e6。而此种情况,便可以想到需要使用离散化。 

2.而离散化的时候,有两种离散化的情况,

(1)离散化后需要保序,也就是需要原先x < y, 离散化后 get(x) < get(y),

这种方式就是之前学过的,先sort 。  然后 e.erase(unique( e.begin(),e.end() ), e.end() ).

(2)离散化后不需要保序, 则可以直接使用哈希 unordered_map<int,int> q. 

判断这个值x是否再哈希中,q.count(x),  如果再,直接return q[x];

如果不在 q[x] = ++idx;

return q[x];

 2.并查集:

离散化了x1,x2后,就需要判断是否所给条件矛盾。

而我们可以发现,

先给出的条件得到,a 与 b 相等后。 再给出 a 与 b 不相等。矛盾

先给出的条件得到,a 与 b 不相等后, 再给出a 与 b 相等, 也矛盾

也就是矛盾的情况,与给出的条件的顺序无关。

那么我们就可以先完成所有给出的条件中,相等的情况。 因为 得到a,b相等之后 再给出a,b不相等则矛盾容易判断。

而a,b相等直接让它们再同一集合中, a,b不相等则不在同一集合中。 

那么矛盾的情况就是a,b已经再同一集合中了,你现在却说要a,b不在同一集合中。

这就用到了并查集的,合并 和 查询 操作。

 代码实现:

# include <iostream>
# include <unordered_map>
using namespace std;

const int N = 2e6 + 10;

int p[N];

int n;

unordered_map <int,int> h;
int idx = 0;

struct edg
{
    int a,b,e;
} edg[N];

int get(int x)
{
    if(!h.count(x))
    {
        h[x] = ++idx;
    }
    return h[x];
}

int find2(int x)
{
    if(p[x] != x)
    {
        p[x] = find2(p[x]);
    }
    return p[x];
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        
        h.clear();
        idx = 0;  // 此两行清空上一次测试数据的影响。
        
        for(int i = 1 ; i <= n ; i++)
        {
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            edg[i] = {get(x),get(y),z};
        }

        for(int i = 1 ; i <= 2 * n ; i++)
        {
            p[i] = i;
        }

        for(int i = 1; i <= n ; i++)
        {
            if(edg[i].e == 1)
            {
                int temp1 = find2(edg[i].a);
                int temp2 = find2(edg[i].b);
                p[temp1] = temp2;
            }
        }
        bool flag = true;
        for(int i = 1 ; i <= n ; i++)
        {
            if(edg[i].e == 0)
            {
                int temp1 = find2(edg[i].a);
                int temp2 = find2(edg[i].b);
                if(temp1 == temp2)
                {
                    flag = false;
                    break;
                }
            }
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}

标签:约束条件,相等,int,查集,离散,满足,自动,x2,x3
来源: https://blog.csdn.net/qq_49120553/article/details/118760820

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有