算法问题实战策略 MEETINGROOM 附一份tarjan模板

地址 https://algospot.com/judge/problem/read/MEETINGROOM

解答  2-sat 代码样例过了 没有ac。 我又没有正确代码对拍。。。。。 

已确认是输出问题 修改完成

  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()/2; i+=2) {
151                 if (v[i] == 1) {
152                     cout << meetings[i].first << ' ' << meetings[i].second << endl;
153                 }
154                 else {
155                     cout << meetings[i+1].first << ' ' << meetings[i+1].second << endl;
156                 }
157             }
158         }
159     }
160 
161 
162     return 0;
163 }
View Code

一份tarjan 模板

 1 // 11111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 
 4 #include "pch.h"
 5 #include <iostream>
 6 #include <vector>
 7 #include <stack>
 8 #include <algorithm>
 9 
10 using namespace std;
11 
12 const int maxn = 2e5 + 7;
13 vector<int> E[maxn];
14 int vis[maxn];
15 int dfn[maxn], low[maxn], tot, n, ans = maxn;
16 stack<int> s;
17 
18 void tarjan(int x)
19 {
20     low[x] = dfn[x] = ++ tot;
21     s.push(x); vis[x] = 1;
22 
23     for (int i = 0; i < E[x].size(); i++) {
24         int v = E[x][i];
25         if (!dfn[v]) {
26             tarjan(v);
27             low[x] = min(low[x], low[v]);
28         }
29         else if (vis[v]) {
30             low[x] = min(low[x], dfn[v]);
31         }
32     }
33 
34     if (low[x] == dfn[x]) {
35         int cnt = 0;
36         while (1) {
37             int now = s.top();
38             s.pop();
39             vis[x] = 0;
40             cnt++;
41             if (now == x) break;
42         }
43         if (cnt > 1) ans = min(ans, cnt);
44     }
45 
46 }
47 
48 int main()
49 {
50     scanf("%d",&n );
51     for (int i = 1; i <= n; i++) {
52         int x;
53         scanf("%d", &x);
54         E[i].push_back(x);
55     }
56 
57     for (int i = 1; i <= n; i++) {
58         if (!dfn[i])
59             tarjan(i);
60     }
61 
62     cout << ans << endl;
63 
64     return 0;
65 }
tarjan模板
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
阿里打赏 微信打赏
原文地址:https://www.cnblogs.com/itdef/p/11822234.html