時間限制:2s,空間256mb
問題描述
n個變數和m個「相等」或「不相等」的約束條件,請你判定是否存在一種賦值方案滿足所有m個約束條件。
輸入第一行乙個整數t,表示資料組數。(t<=100)
接下來會有t組資料,對於每組資料:
第一行是兩個整數n,m,表示變數個數和約束條件的個數。(1<=n,m<=500000)
接下來m行,每行三個整數a,b,e(1<=a,b<=n),表示第a個變數和第b個變數的關係:
保證所有資料的n總和不超過500000。
輸出輸出t行,第i行表示第i組資料的答案。若第i組資料存在一種方案則輸出"yes";否則輸出"no"(不包括引號)。
輸入樣例
2
5 51 2 1
2 3 1
3 4 1
1 4 1
2 5 0
3 31 2 1
2 3 1
1 3 0
輸出樣例yes
no
樣例解釋
對於第一組資料,有5個約束:
顯然我們可以令:
故第一組資料輸出"yes"。
對於第二組資料,有3個約束:
由前兩個約束可推出變數1=變數3,但第三個約束表明變數1≠變數3,矛盾。
故第二組資料輸出"no"。
#include
using
namespace std;
// ***************== **實現開始 ***************==
const
int n =
300005
;// fanther:每個節點的父親節點
// rank:節點的秩(用於啟發式合併)
int father[n]
,rank[n]
;//查詢節點x所在集合的根
intfind
(int x)
// 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)
int cnt =0;
for(
int i=
0; i++i)
//將e=1的操作提到e=0的操作前
if(e[i]==1
)for
(int i=
0; i++i)
}// e[i]==1 即 a[i]與b[i]有共同的父親節點
else}}
return
"yes";}
// ***************== **實現結束 ***************==
intmain()
printf
("%s\n"
,getanswer
(n, m, a, b, e)
.c_str()
);}return0;
}
清華大學演算法訓練營 象棋
你有足夠多的象棋 車 在乙個n n的棋盤上你能放多少個 車 呢?注意,所給棋盤上有些位置不能放任何東西。同時,某一行 列 最多只能存在乙個 車 第一行為乙個正整數n。1 n 500 接下來n行,每行包含n個整數,若為0表示這個位置不能放 車 若為1表示這個位置可以放 車 輸出乙個整數,表示最多能放多...
清華大學演算法訓練營 重編碼
重編碼 priority queue 有一篇文章,文章包含 n種單詞,單詞的編號從 1 至 n,第 i 種單詞的出現次數為 w i 現在,我們要用乙個 2 進製串 即只包含 0 或 1 的串 s i 來替換第 i 種單詞,使其滿足如下要求 對於任意的 1 i,j n i j 都有 s i 不是 s ...
清華大學演算法訓練營 序列計數
給定乙個n個整數的序列以及乙個非負整數d,請你輸出這個序列中有多少個連續子串行 長度大於1 滿足該子串行的最大值最小值之差不大於d。如 序列1 2 3中長度大於1的連續子串行有 1 2 2 31 2 3第一行包含兩個整數n,d。1 n 300000,0 d 2000000000 接下來一行包含n個整...