佈置宴席最微妙的事情,就是給前來參宴的各位賓客安排座位。不管如何,總不能把兩個死對頭排到同一張宴會桌旁!這個艱鉅任務如今就交給你,對任何一對客人,請編寫程序告訴主人他們是否能被安排同席。html
輸入第一行給出3個正整數:N
(≤100),即前來參宴的賓客總人數,則這些人從1到N
編號;M
爲已知兩兩賓客之間的關係數;K
爲查詢的條數。隨後M
行,每行給出一對賓客之間的關係,格式爲:賓客1 賓客2 關係
,其中關係
爲1表示是朋友,-1表示是死對頭。注意兩我的不可能既是朋友又是敵人。最後K
行,每行給出一對須要查詢的賓客編號。數據結構
這裏假設朋友的朋友也是朋友。但敵人的敵人並不必定就是朋友,朋友的敵人也不必定是敵人。只有單純直接的敵對關係纔是絕對不能同席的。spa
對每一個查詢輸出一行結果:若是兩位賓客之間是朋友,且沒有敵對關係,則輸出No problem
;若是他們之間並非朋友,但也不敵對,則輸出OK
;若是他們之間有敵對,然而也有共同的朋友,則輸出OK but...
;若是他們之間只有敵對關係,則輸出No way
。code
7 8 4 5 6 1 2 7 -1 1 3 1 3 4 1 6 7 -1 1 2 1 1 4 1 2 3 -1 3 4 5 7 2 3 7 2
No problem OK OK but... No way
並查集介紹:htm
並查集是一種樹型的數據結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題;blog
經常使用操做有:遞歸
#include<stdio.h> #include<stdlib.h> #include<malloc.h> int Rela[110][110];//關係 int Parent[110];//上一個節點,同一組的組長的上一節點號爲本身的號 void Init_Parent_Rela(int N) { for(int i=1; i<=N; i++){ Parent[i] = i;//初始化根節點爲本身 => 並查集的初始化 for(int j=1; j<=N; j++){ Rela[i][j] = 0; Rela[j][i] = 0; } } } int GetOriNode(int pos)//找根節點,根節點相同則在同一組中 => 並查集的查找 { if(Parent[pos] == pos)//若是上一節點號是本身則找到,返回 return pos; else{//不是則遞歸 int index = GetOriNode(Parent[pos]); return index; } } int Union(int m1, int m2)//=> 並查集的合併 { if(GetOriNode(m1) != GetOriNode(m2)){//根節點不一致 int parent = GetOriNode(m1);//找到m1的根節點 Parent[parent] = GetOriNode(m2);//將m1的根節點的號改爲m2的根節點號,即將二者劃到同一組 } } int main() { int N, M, K; scanf("%d %d %d", &N, &M, &K); Init_Parent_Rela(N); for(int i=0; i<M; i++){ int m1, m2, rela; scanf("%d %d %d", &m1, &m2, &rela); Rela[m1][m2] = rela; Rela[m2][m1] = rela; if(rela == 1) Union(m1, m2);//是朋友就合併朋友圈 } int m1, m2; for(int i=0; i<K; i++){ scanf("%d %d", &m1, &m2); if(Rela[m1][m2] == 1)//直接朋友 printf("No problem\n"); else if(Rela[m1][m2] == -1){//存在敵對關係 if(GetOriNode(m1) == GetOriNode(m2))//有共同朋友,在同一朋友圈中 printf("OK but...\n"); else//單純的敵對關係 printf("No way\n"); } else printf("OK\n");//不是朋友,我感受不是朋友在統一朋友圈也要輸出"No proble",可是那樣提交錯誤 } }