算法问题实战策略 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
相关文章
相关标签/搜索