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驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    Knockout应用开发指南 第八章:简单应用举例(2)
    微软ASP.NET站点部署指南(7):生产环境部署
    Knockout应用开发指南 第七章:Mapping插件
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(6)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(5)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(3)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(8)
    Microsoft Visual Studio .NET 2003 引导程序插件下载地址(非官方)
    Vs2010在没有安装SQL Server 2005/2008 Express时如何连接MDF数据文件?
  • 原文地址:https://www.cnblogs.com/itdef/p/11822234.html
Copyright © 2011-2022 走看看