算法訓練營:等式
阿新 • • 發佈:2019-02-01
實現 fin 變量 限制 是否 初始 返回 ace esp
題目:
描述
有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"。
限制
對於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
提示
用並查集來維護相等的集合。代碼實現
#include <iostream> #include <vector> using namespace std; // ================= 代碼實現開始 ================= const int N = 300005 ; //Father : 每個節點的父親節點 //Rank : 節點的秩 int Father[N] , Rank[N] ;//查找節點x所有集合的根 // x : 節點x 返回值 :根 int find( int x ){ return Father[x] == x ? x : Father[x] = find( 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 ; //各個節點的秩起初都是0 } // 將 e = 1 都放到 e = 0 前面 int cnt = 0 ; for( int i = 0 ; i < m ; i++ ) { 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++ ) { int setA = find( A[i] ) ; //找到A[i]所有集合的根 int setB = find( B[i] ) ; //找到B[i]所有集合的根 if( E[i] == 0 ) { if( setA == setB ) return "No" ; } else{ if( setA != setB ) { if( Rank[setA] > Rank[setB] ) swap( setA , setB ) ; //RankB 的父節點更高 Father[setA] = setB ; if( Rank[setA] == Rank[setB] ) Rank[setB] ++ ; } } } 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; }
算法訓練營:等式