zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    从 LengthFieldBasedFrameDecoder 看 netty 处理拆包
    nacos 服务的实例变化
    nacos 中的服务和实例
    idea 编译 brooklin
    idea 编译 netty 源码
    consumeQueue 和 indexFile 文件
    rocketMQ 事务消息
    特殊符号存入mysql数据库时报错:Incorrect string value: 'xF0x9Fx98x84xF0x9F的解决方法
    面试中常用排序算法的python实现和性能分析
    获取编写代码所在文件的上级文件和上上级文件的相对路径
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13993123.html
Copyright © 2011-2022 走看看