CF1215F Radio Stations

CF1215F Radio Stations
难啊,没搞懂怎么前缀和优化建边,于是瞄了一眼题解。。。

大概就是对于一个点 (x)(yes(x)) 代表 (f in [1, x])(no(x)) 代表 (f in [x+1, M])。所以对于一个电台的区间 ([l,r]) 即为 (yes(r) & no(l-1))。然后就再开 (2M) 个点表示一下。
剩下就是 ( ext{2-sat}) 板子。
根据情况连边。

  • “至少”连 (lnot x ightarrow y, lnot y ightarrow x)
  • “至多”连 (x ightarrow lnot y, y ightarrow lnot x)
  • 然后框边界 (x ightarrow lnot (P+l-1), (P+l-1) ightarrow lnot x, x ightarrow (P+r), lnot(P+r) ightarrow lnot x)

然后跑 ( ext{2-sat})

/*
	Name:
	Author: Gensokyo_Alice
	Date:
	Description:
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
const ll MAXN = 2e6+10;

ll N, P, M1, M2, _N, cnt, num, vis[MAXN], dfn[MAXN], low[MAXN], head[MAXN], bel[MAXN];
stack <ll> st;

struct edge {
	ll nt, to;
} E[MAXN << 1];

ll no(ll);
ll yes(ll);
bool calc();
void tarjan(ll);
void add(ll, ll);

int main() {
	memset(head, -1, sizeof(head));
	scanf("%lld%lld%lld%lld", &N, &P, &M1, &M2); // 0 ~ P-1;
	for (ll i = 1, x, y; i <= N; i++) {
		scanf("%lld%lld", &x, &y); x--, y--;
		add(no(y), yes(x));
		add(no(x), yes(y));
	}
	for (ll i = 0; i < M1; i++) {
		add(yes(i+P), yes(i+P+1));
		add(no(i+P+1), no(i+P));
	}
	add(yes(P), no(P));
	for (ll l, r, i = 0; i < P; i++) {
		scanf("%lld%lld", &l, &r);
		add(yes(i), no(P+l-1));
		add(yes(P+l-1), no(i)); 
		add(yes(i), yes(P+r));
		add(no(P+r), no(i));
	}
	for (ll i = 1, x, y; i <= M2; i++) {
		scanf("%lld%lld", &x, &y); x--, y--;
		add(yes(x), no(y));
		add(yes(y), no(x));
	}
	if (calc()) {
		ll k = 0;
		for (ll i = 0; i < P; i++) if (bel[yes(i)] < bel[no(i)]) k++;
		for (ll i = 1; i <= M1; i++) if (bel[yes(i+P)] < bel[no(i+P)]) {printf("%lld %lld
", k, i); break;}
		for (ll i = 0; i < P; i++) if (bel[yes(i)] < bel[no(i)]) printf("%lld ", i+1);
	} else puts("-1");
    return 0;
}

ll no(ll x) {return x << 1 | 1;}
ll yes(ll x) {return x << 1;}

bool calc() {
	for (ll i = 0; i <= no(M1+P); i++) if (!dfn[i]) tarjan(i);
	for (ll i = 0; i <= M1+P; i++) if (bel[yes(i)] == bel[no(i)]) return false;
	return true;
}

void tarjan(ll n) {
	dfn[n] = low[n] = ++num;
	st.push(n); vis[n] = 1;
	for (ll i = head[n]; ~i; i = E[i].nt) {
		ll v = E[i].to;
		if (!dfn[v]) {
			tarjan(v);
			low[n] = min(low[v], low[n]);	
		} else if (vis[v]) low[n] = min(dfn[v], low[n]);
	}
	if (dfn[n] == low[n]) {
		_N++;
		ll t;
		do {
			t = st.top();
			st.pop();
			bel[t] = _N;
			vis[t] = 0;
		} while (t != n);
	}
}

void add(ll x, ll y) {
	cnt++;
	E[cnt].to = y;
	E[cnt].nt = head[x];
	head[x] = cnt;
}
原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13993123.html