邓俊辉 算法训练营练习 - 等式(启发式合并)

等式
描述
有n个变量和m个“相等”或“不相等”的约束条件,请你判定是否存在一种赋值方案满足所有m个约束条件。

输入
第一行一个整数T,表示数据组数。

接下来会有T组数据,对于每组数据:

第一行是两个整数n,m,表示变量个数和约束条件的个数。

接下来m行,每行三个整数a,b,e,表示第a个变量和第b个变量的关系:

若e=0则表示第a个变量不等于第b个变量;
若e=1则表示第a个变量等于第b个变量
输出
输出T行,第i行表示第i组数据的答案。若第i组数据存在一种方案则输出"Yes";否则输出"No"(不包括引号)。

输入样例1
2
5 5
1 2 1
2 3 1
3 4 1
1 4 1
2 5 0
3 3
1 2 1
2 3 1
1 3 0
输出样例1
Yes
No

#include <bits/stdC++.h>
using namespace std;

const int len = 300005;
//rankl 判断集合归并到哪家(即 低的一家的父亲节点 认 高的一家父亲节点做父亲节点)
//father 用于父亲节点的记录
int rankl[len];
int father[len];
//find父亲节点
int find(int x){
    //如果father[x] == x则x的父亲节点就是自己(即没有父亲节点)
    //否则继续查找 自己的父亲节点
    return father[x] == x?x:father[x] = find(father[x]);
}
//判断 得出 结论
string getAnswer(int m, int n, vector<int> A, vector<int> B, vector<int> E){
    for(int i = 1;i <= n;i++){
        //初始化 一开始 父亲节点都是 自己
        //一开始各个集合的 秩都是 0
        father[i] = i;
        rankl[i] = 0;
    }
    //E = 1提前
    int cnt = 0;
    for(int i=0; i<m; ++i)  //将e=1的操作提到e=0的操作前
       if(E[i] == 1) {
          swap(E[i], E[cnt]);
          swap(A[i], A[cnt]);
          swap(B[i], B[cnt]);
          ++cnt;
    }
    // 循环条件
    for(int i = 0;i < m;i++){
        //找出A[i] 与 B[i]的最高父亲节点
        int setA = find(A[i]);
        int setB = find(B[i]);
        // 如果E[i] = 0 判断 如果 A[i] 和 B[i]的父亲节点相同说明 两个在一个集合中 则 此条件错误
        if(E[i] == 0){
            if(setA == setB)
                return "No";
        }
        else{
            //判断 谁的秩高 低的集合的父亲节点认高的集合的父亲节点做父节点
            if(rankl[setA] < rankl[setB])
                father[setA] = setB;
            else{
                father[setB] = setA;
                // 如果 两个节点父亲节点的秩的大小相同 则默认让 A[i] 做父亲节点
                if(setA == setB)
                    rankl[setA] += 1;//相同时认A[i]做父亲的节点 其秩 + 1
            }
        }
    }
    return "Yes";
}
int main(int argc, char const *argv[]){
    //A B 代表元素 E代表操作
    vector<int> A;
    vector<int> B;
    vector<int> E;

    //m代表判断条件的数量
    //n代表元素数量
    int m,n;
    scanf("%d%d",&m,&n);

    for(int i = 0;i < m;i++){
        int ai,bi,ci;
        scanf("%d%d%d",&ai,&bi,&ci);
        A.push_back(ai);
        B.push_back(bi);
        E.push_back(ci);
    }
    cout << getAnswer(m,n,A,B,E);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/WX_1218639030/article/details/82944519