zoukankan      html  css  js  c++  java
  • P6378 [PA2010] Riddle

    思路:

    两端点至少选一个点作为关键点的问题用2-SAT进行连边处理即可

    本题的难点在于如何维护第二个条件

    朴素建边显然是不行的,我们用设置前缀节点$pre_i$的方法优化建边

    $pre_i$ 表示在x组中的前i个数已经存在关键点$pre_i'$表示在x组中的前i个数不存在关键点

    我们连接$(a,pre_i),(pre_{i-1},pre_{i}).(pre_{i-1},a')$三条边即可对图达成约束

    如果存在某一个集合内不存在关键点的情况,那么将其任意一点设为关键点即可

    #include<bits/stdc++.h>
    #define maxn 8000005
    #define maxm 500005
    #define inf 0x7fffffff
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dgx cerr<<"=============="<<endl
    #define lowbit(x) (x&(-x))
    #define MAXN 4000003
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        while('0'>ch || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while('0'<=ch && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n,m,q,pre1[MAXN],pre2[MAXN],to[maxn],nxt[maxn],fir[MAXN],tot,cnt,a[MAXN],dfn[MAXN],low[MAXN],sta[MAXN],top,num,col[MAXN],cc;
    void ade(int x,int y){
    //    cout<<x<<"-->"<<y<<endl;
        to[++tot]=y;
        nxt[tot]=fir[x];
        fir[x]=tot;
    }
    void Tarjan(int x){
        dfn[x]=low[x]=++num;
        sta[++top]=x;
        for(int k=fir[x];k;k=nxt[k]){
            if(!dfn[to[k]]){
                Tarjan(to[k]);
                low[x]=min(low[x],low[to[k]]);
            }
            else if(!col[to[k]]) low[x]=min(low[x],dfn[to[k]]);
        }
    //    cout<<x<<" "<<low[x]<<" "<<dfn[x]<<endl;
        if(low[x]==dfn[x]){++cc;while(sta[top+1]!=x) col[sta[top]]=cc,top--;}
    }
    int main(){
        n=read(); m=read(); q=read();
        rep(i,1,m){
            int x=read(),y=read();
            ade(x+n,y); ade(y+n,x);
        }cnt=n+n;
        rep(i,1,n) pre1[i]=++cnt,pre2[i]=cnt+n;
        rep(i,1,q){
            int s=read();
            rep(j,1,s){
                a[j]=read();
                ade(a[j],pre1[a[j]]); ade(pre2[a[j]],a[j]+n);
                if(j==1) continue;
                ade(pre1[a[j-1]],pre1[a[j]]) ; ade(pre2[a[j]],pre2[a[j-1]]);
                ade(pre1[a[j-1]],a[j]+n); ade(a[j],pre2[a[j-1]]);
            }
        }
        rep(i,1,4*n) if(!dfn[i]) Tarjan(i);
    //    rep(i,1,4*n) cout<<col[i]<<" ";cout<<endl;
        rep(i,1,n) if(col[i+n]==col[i]){cout<<"NIE"; return 0;}
        rep(i,2*n+1,3*n) if(col[i+n]==col[i]){cout<<"NIE";return  0;}
        cout<<"TAK";
        return 0;
    }
  • 相关阅读:
    Mysql的表名/字段名/字段值是否区分大小写
    20个PHP程序性能优化的方法
    PHP中大括号用法
    PHP伪类型和伪变量
    PHP中关于取模运算及符号
    PHP之array_flip()方法
    PHP之implode()方法
    PHP中is_null()方法
    原型模式(Prototype)
    适配器模式
  • 原文地址:https://www.cnblogs.com/handsome-zlk/p/14467398.html
Copyright © 2011-2022 走看看