Codeforces Round #585 (Div. 2) F. Radio Stations

題意

2SAT2-SAT多了一個邊的範圍,其實只需要把點的範圍加上去就行了即:
ii個點(l[i],r[i])(l[i], r[i]),那麼構造點jjkk對應l[i]l[i]r[i]+1r[i]+1
j<<1j<<1j<<11j<<1|1分別對應val>=l[i]val >= l[i]val<l[i]val < l[i]
k<<1k<<1k<<11k<<1|1分別對應val>=r[i]+1val >= r[i]+1val<r[i]+1val < r[i]+1
這樣連接點i<<1j<<1i<<1 \to j<<1i<<1k<<11i<<1 \to k<<1|1,以及j<<11i<<11j<<1|1 \to i<<1|1k<<1i<<11k<<1 \to i<<1|1
然後把0M+10 \backsim M+1 的點按邏輯連接起來就行了。

小trick

2SAT2-SAT中一條關係表達式一定能退出兩條有向邊,不能漏邊了!!!

#include <bits/stdc++.h>

using namespace std;

vector<vector<int>> e;
vector<int> l, r;

vector<bool> vis;
stack<int> stk;
vector<int> dfn, low, be;
int tot = 0, cnt = 0;

void tarjan(int u)
{
    dfn[u] = low[u] = ++tot;
    stk.push(u);
    vis[u] = true;
    for (auto &v : e[u]) {
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if (vis[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (dfn[u] == low[u]) {
        ++cnt;
        // cout << "stk: ";
        while (stk.top() != u) {
            int v = stk.top(); stk.pop();
            // cout << v << " ";
            be[v] = cnt;
            vis[v] = false;
        }
        // cout << u << endl;
        stk.pop();
        be[u] = cnt;
        vis[u] = false;
    }
}

int main()
{
    int n, p, M, m;
    cin >> n >> p >> M >> m;
    const int maxn = (p + M + 1) * 2 + 10;
    e.assign(maxn, vector<int>());
    l.assign(p, 0);
    r.assign(p, 0);
    int x, y;
    for (int i = 0; i < n; ++i) {
        cin >> x >> y;
        --x; --y;
        e[x<<1|1].emplace_back(y<<1);    
        e[y<<1|1].emplace_back(x<<1);
    }
    for (int i = 0; i < p; ++i) {
        cin >> l[i] >> r[i];
        e[i<<1].emplace_back((l[i] + p)<<1);
        e[i<<1].emplace_back((r[i] + p + 1)<<1|1);
        e[(l[i] + p)<<1|1].emplace_back(i<<1|1);
        e[(r[i] + p + 1)<<1].emplace_back(i<<1|1);
    }
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        --x; --y;
        e[x<<1].emplace_back(y<<1|1);
        e[y<<1].emplace_back(x<<1|1);
    }
    for (int i = 0; i <= M; ++i) {
        e[(i + p + 1)<<1].emplace_back((i + p)<<1);
        e[(i + p)<<1|1].emplace_back((i + p + 1)<<1|1);
    }
    vis.assign(maxn, false);
    dfn.assign(maxn, 0);
    low.assign(maxn, 0);
    be.assign(maxn, 0);
    for (int i = 0, _i = 2 * (p + M + 1); i <= _i; ++i)
        if (!dfn[i])
            tarjan(i);
    for (int i = 0, _i = p + M + 1; i <= _i; ++i) {
        if (be[i<<1] == be[i<<1|1]) {
            cout << -1 << endl;
            return 0;
        }
    }
    vector<int> ans;
    int val = 0;
    for (int i = 0; i < p; ++i) {
        // cout << "i: " << be[i<<1] << " " << be[i<<1|1] << endl;
        if (be[i<<1] < be[i<<1|1]) {
            ans.emplace_back(i);
            val = max(val, l[i]);
        }
    }
    cout << ans.size() << " " << val << "\n";
    for (int i = 0, _i = ans.size(); i < _i; ++i) {
        if (i)
            cout << " ";
        cout << ans[i] + 1;
    } 
    cout << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章