地址 https://algospot.com/judge/problem/read/MEETINGROOMios
解答 2-sat 代碼樣例過了 沒有ac。 我又沒有正確代碼對拍。。。。。算法
todo數組
1 #include <algorithm> 2 #include <iostream> 3 #include <vector> 4 #include <stack> 5 6 using namespace std; 7 8 vector<vector<int>> adj; 9 10 vector<int> sccId, discovered, finished; 11 stack<int> st; //保存頂點序號的棧 12 int sccCounter, vertexCounter; 13 14 //返回以here爲根節點的子樹中 15 //可以到達後向邊的最小發現順序 16 int scc(int here) { 17 int ret = discovered[here] = vertexCounter++; 18 //將here存入棧,here的全部後代節點都會在here以後進棧 19 st.push(here); 20 21 for (int i = 0; i < adj[here].size();++i) { 22 int there = adj[here][i]; 23 //(here,there)是樹邊 24 if (discovered[there] == -1) 25 ret = min(ret, scc(there)); 26 else if (discovered[there] < discovered[here] && finished[there] != 1) 27 ret = min(ret, discovered[there]); 28 } 29 30 //判斷here是否爲強聯通份量的根節點 31 if (ret == discovered[here]) { 32 //以here爲根節點的子樹中,將剩餘全部頂點所有綁定爲同一份量 33 while (true) { 34 int t = st.top(); 35 st.pop(); 36 sccId[t] = sccCounter; 37 if (t == here) break; 38 } 39 ++sccCounter; 40 } 41 42 finished[here] = 1; 43 return ret; 44 } 45 46 47 //tarjan 的scc算法 48 vector<int> tarjanSCC() { 49 //數組和計數器的初始化 50 sccId = discovered = finished = vector<int>(adj.size(), -1); 51 sccCounter = vertexCounter = 0; 52 53 //對全部頂點調用scc() 54 for (int i = 0; i < adj.size(); ++i) 55 if (discovered[i] == -1) scc(i); 56 return sccId; 57 } 58 59 60 //======================================================================== 61 //圖的領接表表示法 62 //vector<vector<int>> adj; 63 64 bool disjoint(const pair<int, int>& a, const pair<int, int>& b) { 65 return a.second <= b.first || b.second <= a.first; 66 } 67 68 //若是meetings[]表示各隊提出的開會時間 69 //則將此題轉換爲2-SAT問題後生成蘊含圖 70 //第i個團隊須要選擇meetings[2*i]或meetings[2*i+1]時候之一開會 71 void makeGraph(const vector<pair<int, int>>& meetings) 72 { 73 int vars = meetings.size(); 74 75 //每一個變量對應圖的兩個頂點 76 adj.clear(); adj.resize(vars * 2); 77 for (int i = 0; i < vars; i += 2) { 78 //各團隊須要選擇第i號和第j號會議之一 79 //添加(i or j )句子 80 int j = i + 1; 81 adj[i * 2 + 1].push_back(j * 2); 82 adj[j * 2 + 1].push_back(i * 2); 83 } 84 85 for (int i = 0; i < vars; ++i) { 86 for (int j = 0; j < i; ++j) { 87 //第i號會議和第j號會議重疊 88 if (!disjoint(meetings[i], meetings[j])) { 89 //放棄第i個會議 或者放棄第j個會議 90 //添加 (~i or ~j)子句 91 adj[i * 2].push_back(j * 2 + 1); 92 adj[j * 2].push_back(i * 2 + 1); 93 } 94 } 95 } 96 } 97 98 99 vector<int> solve2SAT() 100 { 101 int n = adj.size() / 2; 102 vector<int> label = tarjanSCC(); 103 104 for (int i = 0; i < 2 * n; i += 2) 105 if (label[i] == label[i + 1]) 106 return vector<int>(); 107 108 vector<int> value(2 * n, -1); 109 110 vector<pair<int, int>> order; 111 for (int i = 0; i < 2 * n; i++) 112 order.push_back(make_pair(label[i], i)); 113 sort(order.begin(), order.end()); 114 115 for (int i = 0; i < 2 * n; ++i) { 116 int vertex = order[i].second; 117 int variable = vertex / 2, isTrue = vertex % 2; 118 if (value[variable] != -1) continue; 119 value[variable] = !isTrue; 120 } 121 return value; 122 } 123 124 125 126 127 int main() 128 { 129 int n; 130 cin >> n; 131 132 while (n--) { 133 int m; 134 cin >> m; 135 vector<pair<int, int>> meetings; 136 while (m--) { 137 int a, b, c, d; 138 cin >> a >> b >> c >> d; 139 meetings.push_back(make_pair(a, b)); 140 meetings.push_back(make_pair(c, d)); 141 } 142 makeGraph(meetings); 143 144 vector<int> v = solve2SAT(); 145 if (v.empty()) { 146 cout << "IMPOSSIBLE" << endl;; 147 } 148 else { 149 cout << "POSSIBLE" << endl; 150 for (int i = 0; i < v.size(); i++) { 151 if (v[i] == 1) { 152 cout << meetings[i].first << ' ' << meetings[i].second <<endl; 153 } 154 } 155 } 156 } 157 158 159 return 0; 160 }