等式
描述
有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
样例1解释
一共有2组数据。
对于第一组数据,有5个约束:
- 变量1=变量2
- 变量2=变量3
- 变量3=变量4
- 变量1=变量4
- 变量2≠变量5
显然我们可以令:
- 变量1=变量2=变量3=变量4=任意一个数值
- 变量5=任意一个和变量2不同的数值
故第一组数据输出"Yes"。 对于第二组数据,有3个约束:
- 变量1=变量2
- 变量2=变量3
- 变量1≠变量3
由前两个约束可推出变量1=变量3,但第三个约束表明变量1≠变量3,矛盾。
故第二组数据输出"No"。
输入样例2
限制
对于10%的数据,n,m ≤ 5,T ≤ 5;
对于50%的数据,n,m ≤ 1000,T ≤ 10;
对于100%的数据,1 ≤ n,m ≤ 500000,1 ≤ a,b ≤ n,T ≤ 100。
保证所有数据的n总和与m总和不超过500000。
时间:2 sec
空间:256 MB
提示
[用并查集来维护相等的集合。]
[改编自 NOI 2015 day1 T1 程序自动分析]
#include <bits/stdc++.h>
using namespace std;
const int N = 300005;
// ================= 代码实现开始 =================
int Father[N],Rank[N];
/* 请在这里定义你需要的全局变量 */
int find(int x){
while(Father[x]!=x){ x=Father[x];}
return x;}
/*
int getfather(int x) {
if(x != father[x])
father[x] = getfather(father[x]); // 路径压缩
return father[x];
} */
// 给定n个变量以及m个约束,判定是否能找出一种赋值方案满足这m个约束条件
// n:如题意
// m:如题意
// A:大小为m的数组,表示m条约束中的a
// B:大小为m的数组,表示m条约束中的b
// E:大小为m的数组,表示m条约束中的e
// 返回值:若能找出一种方案,返回"Yes";否则返回"No"(不包括引号)。
string getAnswer(int n, int m, vector<int> A, vector<int> B, vector<int> E) {
/* 请在这里设计你的算法 */
for(int i = 1;i<=n;i++){
Father[i]= i;
Rank[i]=0;
}
int cnt = 0;
for(int i = 0;i<m;i++){
if(E[i]==1){swap(A[i],A[cnt]);
swap(B[i],B[cnt]);
swap(E[i],E[cnt]);
cnt++;}
}
for (int i = 0;i<m;i++){
int seta = find(A[i]);
int setb = find(B[i]);
if(E[i]==0){
if(seta==setb) return "No";
}else{
if(seta!=setb) {
if(Rank[seta]>Rank[setb])Father[setb]=seta;
else{
Father[setb]=seta;
if(Rank[seta]=Rank[setb])
{Rank[seta]++;}
}
}
}
}return "Yes";}
// ================= 代码实现结束 =================
int main() {
int T;
for (scanf("%d", &T); T--; ) {
int n, m;
scanf("%d%d", &n, &m);
vector<int> A, B, E;
for (int i = 0; i < m; ++i) {
int a, b, e;
scanf("%d%d%d", &a, &b, &e);
A.push_back(a);
B.push_back(b);
E.push_back(e);
}
printf("%s\n", getAnswer(n, m, A, B, E).c_str());
}
return 0;
}