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

题意

2 − S A T 2-SAT 2SAT多了一个边的范围,其实只需要把点的范围加上去就行了即:
i i i个点 ( l [ i ] , r [ i ] ) (l[i], r[i]) (l[i],r[i]),那么构造点 j j j k k k对应 l [ i ] l[i] l[i] r [ i ] + 1 r[i]+1 r[i]+1
j < < 1 j<<1 j<<1 j < < 1 ∣ 1 j<<1|1 j<<11分别对应 v a l > = l [ i ] val >= l[i] val>=l[i] v a l < l [ i ] val < l[i] val<l[i]
k < < 1 k<<1 k<<1 k < < 1 ∣ 1 k<<1|1 k<<11分别对应 v a l > = r [ i ] + 1 val >= r[i]+1 val>=r[i]+1 v a l < r [ i ] + 1 val < r[i]+1 val<r[i]+1
这样连接点 i < < 1 → j < < 1 i<<1 \to j<<1 i<<1j<<1 i < < 1 → k < < 1 ∣ 1 i<<1 \to k<<1|1 i<<1k<<11,以及 j < < 1 ∣ 1 → i < < 1 ∣ 1 j<<1|1 \to i<<1|1 j<<11i<<11 k < < 1 → i < < 1 ∣ 1 k<<1 \to i<<1|1 k<<1i<<11
然后把 0 ∽ M + 1 0 \backsim M+1 0M+1 的点按逻辑连接起来就行了。

小trick

2 − S A T 2-SAT 2SAT中一条关系表达式一定能退出两条有向边,不能漏边了!!!

#include 

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;
}

你可能感兴趣的:(CF)