算法問題實戰策略 MEETINGROOM

地址 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 }
View Code
相關文章
相關標籤/搜索