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\) 个点表示一下。
剩下就是 \(\text{2-sat}\) 板子。
根据情况连边。
- “至少”连 \(\lnot x \rightarrow y, \lnot y \rightarrow x\)
- “至多”连 \(x \rightarrow \lnot y, y \rightarrow \lnot x\)
- 然后框边界 \(x \rightarrow \lnot (P+l-1), (P+l-1) \rightarrow \lnot x, x \rightarrow (P+r), \lnot(P+r) \rightarrow \lnot x\)
然后跑 \(\text{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\n", 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;
}
希望我们都有一个光明的未来