• #2-SAT,Tarjan,前缀优化建边#洛谷 6378 [PA2010]Riddle


    题目

    (n) 个点 (m) 条边的无向图被分成 (k) 个部分。每个部分包含一些点。

    请选择一些关键点,使得每个部分恰有一个关键点,且每条边至少有一个端点是关键点。


    分析

    每条边至少有一个端点是关键点很好做就是(x'->y,y'->x)
    考虑每个部分恰有一个怎么做,不可能暴力建边,
    考虑把前(i)个是否选新开节点,那么就得满足
    (pre_{a_{i-1}}->a_{i}'qquad a_i->pre_{a_{i-1}}')(选择(1sim i-1)就不能选(i),反之亦然)
    (a_i->pre_{a_i}qquad pre_{a_i}'->a_i')(选择(i)就一定选择(1sim i),反之亦然)
    (pre_{a_i}'->pre_{a_{i-1}}'qquad pre_{a_{i-1}}->pre_{a_i})(选择(1sim i-1)就一定选择(1sim i),反之亦然)
    这样就能强制保证每个部分有且仅有一个,套2-SAT模板就行了


    代码

    #include <cstdio>
    #include <cctype>
    #include <stack>
    #define rr register
    using namespace std;
    const int N=4000011; struct node{int y,next;}e[N<<1];
    int dfn[N],low[N],v[N],as[N],col[N],tot,cnt,et,n,m,k; stack<int>stac;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline void add(int x,int y){e[++et]=(node){y,as[x]},as[x]=et;}
    inline signed fal(int x){return x+n;};
    inline signed tru(int x){return x;}
    inline signed sub(int x){return x+n*2;}
    inline void tarjan(int x){
    	dfn[x]=low[x]=++tot,v[x]=1,stac.push(x);
    	for (rr int i=as[x];i;i=e[i].next)
    	if (!dfn[e[i].y]){
    		tarjan(e[i].y);
    		low[x]=min(low[x],low[e[i].y]);
    	}else if (v[e[i].y])
    	    low[x]=min(low[x],dfn[e[i].y]);
    	if (dfn[x]==low[x]){
    		rr int y; ++cnt;
    		do{
    			y=stac.top(),stac.pop();
    			v[y]=0,col[y]=cnt;
    		}while (x^y);
    	}
    }
    signed main(){
    	n=iut(); m=iut(); k=iut();
    	for (rr int i=1;i<=m;++i){
    		rr int x=iut(),y=iut();
    		add(fal(x),tru(y)),add(fal(y),tru(x));
    	}
    	for (rr int i=1,t;i<=k;++i){
    		t=iut();
    		for (rr int j=1;j<=t;++j){
    			rr int x=iut();
    			add(tru(x),tru(sub(j+tot))),
    			add(fal(sub(j+tot)),fal(x));
    			if (j>1){
    				add(tru(sub(j-1+tot)),tru(sub(j+tot))),
    				add(fal(sub(j+tot)),fal(sub(j-1+tot))),
    				add(tru(x),fal(sub(j-1+tot))),
    				add(tru(sub(j-1+tot)),fal(x));
    			}
    		}
    		tot+=t;
    	}
    	tot=0;
    	for (rr int i=1;i<=n*4;++i) if (!dfn[i]) tarjan(i);
    	for (rr int i=1;i<=n;++i)
    	if (col[tru(i)]==col[fal(i)])
    	    return !printf("NIE");
    	for (rr int i=1;i<=n;++i)
    	if (col[tru(sub(i))]==col[fal(sub(i))])
    	    return !printf("NIE");
    	return !printf("TAK");
    } 
    
  • 相关阅读:
    Spring Security简介与入门Demo
    电商项目之多功能增删改查案例
    linux-用户管理
    zabbix3.4配置第三方邮件报警
    zabbix3.4配置客户端配置
    centos7上安装zabbix3.4的详细步骤与问题处理记录
    MyBatis日记(五):一对一关系,一对多关系
    MyBatis日记(四):MyBatis——insert、update、delete、select
    Python日记(二):Python之禅
    Python日记(一):拜见小主——Python
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13928921.html
走看看 - 开发者的网上家园