zoukankan      html  css  js  c++  java
  • 算法问题实战策略 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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    MySql常用命令
    多线程
    redhat7.7(centOS7)安装ORACLE 11g出坑教程及问题总结与解决
    使用 CGImageRef 出现的crash
    leetcode238. 除自身以外数组的乘积
    通过位运算实现求和
    leetcode求1+2+……+n
    leetcode101. 对称二叉树
    leetcode198. 打家劫舍
    leetcode394. 字符串解码
  • 原文地址:https://www.cnblogs.com/itdef/p/11822234.html
Copyright © 2011-2022 走看看