題目:
題意:輸入三個數m, p, q 分別表示接下來的輸入行數,天使數目,惡魔數目;
接下來m行輸入形如x, y, ch,ch為yes表示x說y是天使,ch為no表示x說y不是天使(x, y為天使,惡魔的編號,1<=x,y<=p+q);天使只說真話,惡魔只說假話;
如果不能確定所有天使的編號,輸出no,若能確定,輸出所有天使的編號,並且以end結尾;
注意:可能會有連續兩行一樣的輸入;還有,若x==y,x為天使;
思路:種類並查集+dp;
我們分析輸入的資料不難發現,對於輸入x, y, yes,假設x為天使,則y也為為天使,若x為惡魔,那麼y也為惡魔,即x, y, 同為惡魔或者天使;
對於輸入x, y, no,同理可得x, y, 一者為天使一者為惡魔;即可得ch為yes時,x, y, 屬同種,ch為no時, x, y屬異種;
那麼我們很容易就能想到種類並查集,rank[x]表示x與其父親節點的關係,rank[x]=0表示x與其父親節點屬於同類,rank[1]表示x與其父親節點屬於異類;通過並查集將能確定相對關係的編號放在乙個集合裡面,每個結合裡面的編號可以分為兩部分,和根節點屬同種的的節點,以及和根節點屬於異種的節點;這樣並不能直接確定答案,我們確定了劃分集合的個數以及每個集合裡面和根節點同種的節點數目以及異節點的數目;從每個集合裡面選擇一種節點,若所有選中的節點數目和為p的選擇方法唯一,那麼我們能夠確定所有天使的編號,反之則不能;關於這個問題我們可以用dp完美解決;
事實上這個題目前面的並查集部分只是乙個普通的種類並查集,這個記錄路徑的dp才是本題解的精妙部分;我們先用乙個tot變數來儲存集合個數(對於x==y的情況,我們讓x單獨為乙個集合),並且用gg陣列來標記所有編號屬於的集合;用tag陣列儲存每個集合兩種種類的數目;dp[i][j]表示到第i個集合選擇種類的和為j的方法總數,即dp[tot][p]==1時能確定答案;對於dp過程中的每個選擇我們用jj陣列記錄,然後反推選擇路徑用cc陣列記錄路徑就ok啦~
**:
1 #include 2 #include 3 #include4#define maxn 600
5using
namespace
std;67
int pre[maxn], rank[maxn], gg[maxn], jj[maxn][maxn], tag[maxn][2], dp[maxn][maxn], cc[maxn][2];8
9int find(int
x)15
return
pre[x];16}
1718
void jion(int x, int y, int
d)25}26
27int main(void)33
for(int i=1; i<=p+q; i++)
37while(m--)
44jion(x, y, d);45}
46 memset(gg, 0, sizeof(gg)); //
**gg儲存集合個數並且給他們編號
47 memset(jj, 0, sizeof
(jj));
48 memset(tag, 0, sizeof
(tag));
49 memset(dp, 0, sizeof
(dp));
50 memset(cc, 0, sizeof
(cc));
51int tot=0;52
for(int i=1; i<=p+q; i++)56}
57for(int i=1; i<=p+q; i++)
60 dp[0][0]=1;61
for(int i=1; i<=tot; i++)
67if(j-tag[i][1]>=0&&dp[i-1][j-tag[i][1
]])71}72
}73if(dp[tot][p]!=1
)else
else
82 j-=jj[i][j];83}
84for(int i=1; i<=p+q; i++)88}
89 printf("
end\n");
90}91}
92return0;
93 }
poj 1417 種類並查集 普通dp
題意就是 現在這裡有兩群人,一群人只會說真話,另一群人只會說假話,但你不知道這些人中哪些是說真話的,所以你就去問,然後得出一些資訊,其中你只問了是不是說真話的人這乙個問題。現在讓你去判斷這兩群人中哪些人是說真話的,如果可以判斷請按照公升序把說真話的人的編號說出,如果不能,輸出no 分析 首先對於這道...
poj1182 種類並查集
有點坑的題目,不過做做絕對利大於弊,尤其在你不斷wa到哭的時候,大神忽略這句 0 兩者相同級別 1 被根節點吃 2 吃根節點 原因 對於輸入的關係1和2,減1之後便是輸入的兩個量之間的關係 其實是寫完題目之後看解題報告發現這規律的 include include using namespace st...
POJ 1703 種類並查集
題意 乙個城市裡面有兩個黑幫 有兩種操作 a ask 詢問 x,y的關係 d x,y是一夥的 很明顯是種類並查集 於是就yy一下 relationsi 表示與父節點的關係 fatheri 記錄父節點 在合併和查詢root的時候 relations 更新注意一下就可以了 include include...