10004 Bicoloring

題目原文

題目說明
只有兩種顏色,且相鄰兩點需不同色,若可以達成,則輸出 BICOLORABLE,反之輸出 NOT BICOLORABLE。

思路
首先以 vector 建立表格來儲存與某節點相鄰的其他節點,以 queue 來儲存節點走訪的順序。
建立好連通表後,開始走訪,走訪做兩種事情:著色和檢查是否同色,可隨機從某點開始(以下程式碼以 n1 當第一個節點),將其 push 進 queue 裡並著上顏色,塗完顏色後以 current 記住後 pop 出去,
接著開始替相鄰節點(由連通表依序取出)著色,若相鄰節點尚未著色,則 push 到 queue 裡,當作下一個要走訪的 current,並著上與當前 current 相反顏色;已著色則檢查是否與當前 current 同色,同色則可確定非 bicolorable。著完後色都沒問題即為 bicolorable。

簡言之,
1. 建連通表  2. 按連通表依序著色  3. 著色過程中檢查是否符合規定。

  1. #include<cstdio>
  2. #include<vector>
  3. #include<queue>
  4.  
  5. int main()
  6. {
  7. int node;
  8. while(scanf("%d", &node) && node)
  9. {
  10. int edge, n1, n2;
  11. int color[200] = {0};
  12. bool check = true;
  13. std::vector<int> vec[205]; // 所在列數代表它是第幾個點 後面push進和它連接的點
  14. std::queue<int> que;
  15. scanf("%d", &edge);
  16. for(int i = 0; i < edge; i++)
  17. {
  18. scanf("%d %d", &n1, &n2);
  19. vec[n1].push_back(n2); // 建連通表 記得兩邊互相連接
  20. vec[n2].push_back(n1);
  21. }
  22. que.push(n1);
  23. color[n1] = 1;
  24. while(!que.empty() && check) // 開始走訪
  25. {
  26. int current = que.front(); // 先用current存起來
  27. que.pop();
  28. for(int i = 0; i < vec[current].size(); i++)
  29. {
  30. int j = vec[current][i];
  31. if(color[j] == 0) // 還沒上過色
  32. {
  33. que.push(j);
  34. color[j] = -color[current];
  35. }
  36. else if(color[j] == color[current])
  37. {
  38. check = false;
  39. break;
  40. }
  41. }
  42. }
  43. if(check)
  44. printf("BICOLORABLE.\n");
  45. else
  46. printf("NOT BICOLORABLE.\n");
  47. }
  48. }

留言

這個網誌中的熱門文章

機率筆記 (1)

離散數學筆記 — vertex cut

機率筆記 (4) — 隨機變數