算法问题实战策略 MEETINGROOm

地址

解答

todo 

错误代码

  1 // Tarjan_Scc.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
  2 //
  3 
  4 #include "pch.h"
  5 
  6 
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <vector>
 10 #include <stack>
 11 
 12 using namespace std;
 13 
 14 vector<vector<int>> adj;
 15 
 16 vector<int> sccId, discovered, finished;
 17 stack<int> st;    //保存顶点序号的栈
 18 int sccCounter, vertexCounter;
 19 
 20 //返回以here为根节点的子树中
 21 //能够到达后向边的最小发现顺序
 22 int scc(int here) {
 23     int ret = discovered[here] = vertexCounter++;
 24     //将here存入栈,here的所有后代节点都会在here之后进栈
 25     st.push(here);
 26 
 27     for (int i = 0; i < adj[here].size(); i++) {
 28         int there = adj[here][i];
 29         //(here,there)是树边
 30         if (discovered[there] == -1)
 31             ret = min(ret, scc(there));
 32         else if (discovered[there] < discovered[here] && finished[there] != 1)
 33             ret = min(ret, discovered[there]);
 34     }
 35 
 36     //判断here是否为强联通分量的根节点
 37     if (ret == discovered[here]) {
 38         //以here为根节点的子树中,将剩余所有顶点全部绑定为同一分量
 39         while (true) {
 40             int t = st.top();
 41             st.pop();
 42             sccId[t] = sccCounter;
 43             if (t == here) break;
 44         }
 45         ++sccCounter;
 46     }
 47 
 48     finished[here] = 1;
 49     return ret;
 50 }
 51 
 52 
 53 //tarjan 的scc算法
 54 vector<int> tarjanSCC() {
 55     //数组和计数器的初始化
 56     sccId = discovered = finished = vector<int>(adj.size(), -1);
 57     sccCounter = vertexCounter = 0;
 58 
 59     //对所有顶点调用scc()
 60     for (int i = 0; i < adj.size(); ++i)
 61         if (discovered[i] = -1) scc(i);
 62     return sccId;
 63 }
 64 
 65 
 66 //========================================================================
 67 //图的领接表表示法
 68 //vector<vector<int>> adj;
 69 
 70 bool disjoint(const pair<int, int>& a, const pair<int, int>& b){
 71     return a.second <= b.first || b.second <= a.first;
 72 }
 73 
 74 //如果meetings[]表示各队提出的开会时间
 75 //则将此题转换为2-SAT问题后生成蕴含图
 76 //第i个团队需要选择meetings[2*i]或meetings[2*i+1]时候之一开会
 77 void makeGraph(const vector<pair<int, int>>& meetings)
 78 {
 79     int vars = meetings.size();
 80 
 81     //每个变量对应图的两个顶点
 82     adj.clear(); adj.resize(vars*2);
 83     for (int i = 0; i < vars; i += 2) {
 84         //各团队需要选择第i号和第j号会议之一
 85         //添加(i or j )句子
 86         int j = i + 1;
 87         adj[i * 2 + 1].push_back(j * 2);
 88         adj[j * 2 + 1].push_back(i * 2);
 89     }
 90 
 91     for (int i = 0; i < vars; ++i) {
 92         for (int j = 0; j < i; ++j) {
 93             //第i号会议和第j号会议重叠
 94             if (!disjoint(meetings[i], meetings[j])) {
 95                 //放弃第i个会议 或者放弃第j个会议
 96                 //添加 (~i or ~j)子句
 97                 adj[i * 2].push_back(j * 2 + 1);
 98                 adj[j * 2].push_back(i * 2 + 1);
 99             }
100         }
101     }
102 }
103 
104 
105 vector<int> solve2SAT()
106 {
107     int n = adj.size() / 2;
108     vector<int> label = tarjanSCC();
109 
110     for (int i = 0; i < 2 * n; i += 2)
111         if (label[i] == label[i + 1])
112             return vector<int>();
113 
114     vector<int> value(2 * n, -1);
115 
116     vector<pair<int, int>> order;
117     for (int i = 0; i < 2 * n; i++)
118         order.push_back(make_pair(-label[i], i));
119     sort(order.begin(),order.end());
120 
121     for (int i = 0; i < 2 * n; ++i) {
122         int vertex = order[i].second;
123         int variable = vertex / 2, isTrue = vertex % 2;
124         if (value[variable] != -1) continue;
125         value[variable] = !isTrue;
126     }
127     return value;
128 }
129 
130 
131 
132 
133 int main()
134 {
135     int n;
136     cin >> n;
137 
138     while (n--) {
139         int m;
140         cin >> m;
141         vector<pair<int, int>> meetings;
142         while (m--) {
143             int a, b, c, d;
144             cin >> a >> b >> c >> d;
145             meetings.push_back(make_pair(a,b));
146             meetings.push_back(make_pair(a, b));
147         }
148         makeGraph(meetings);
149 
150         vector<int> v = solve2SAT();
151         
152         int i = 9;
153         
154     }
155 
156 }
View Code

猜你喜欢

转载自www.cnblogs.com/itdef/p/11822234.html