luogu P6378 [PA 2010] Riddle / QOJ10674 Riddle [A]

link1 link2

很容易想到 2-SAT。困难的地方在于怎么表示每个区域恰好一个点,如果仅仅把一个点 \(i\) 分为 \(i_0,i_1\) 两个点表示是否关键的话,连边的数量是 \(n^2\) 的。对于每一个区域,我们考虑前缀优化建图,再新建两个点 \(i_2,i_3\) 表示前 \(i\) 个已经选了一个和前 \(i\) 个一个都没选的情况。

建图方式如下:

对于图中的边 \((i,j)\),我们直接让 \(i_0\) 连向 \(j_1\)\(i_1\) 连向 \(j_0\) 即可,这是平凡的。

需要注意的是这样连边虽然能保证每个区域不多于一个关键点,但并不能保证每个区域都至少有一个关键点,对于没有关键点的区域,我们随便选一个当关键点就行了。

#include<bits/stdc++.h>
using namespace std;
const int N=4e6+5,M=1e6+5;
int n,m,k,dfn[N],low[N],idx,cnt,bl[N],pos[N],ans[M],to[N<<1],nxt[N<<1],head[N],tot,st[N],top;
inline void add(int u,int v){
    to[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
inline void dfs(int x){
    dfn[x]=low[x]=++idx;
    st[++top]=x;
    for(int i=head[x],v;i;i=nxt[i]){
        v=to[i];
        if(!dfn[v]){
            dfs(v);
            low[x]=min(low[x],low[v]);
        }else if(!bl[v])low[x]=min(low[x],dfn[v]);
    }
    if(dfn[x]==low[x]){
        cnt++;int u;
        do{
            u=st[top];top--;
            bl[u]=cnt;
        }while(u!=x);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>k;
    for(int i=1,u,v;i<=m;i++){
        cin>>u>>v;
        add(u,v+n);
        add(v,u+n);
    }
    for(int i=1,l,lst,x;i<=k;i++){
        cin>>l;lst=0;
        for(int j=1;j<=l;j++){
            cin>>x;pos[x]=i;
            add(x+n,x+2*n);
            add(x+3*n,x);
            if(j>1){
                add(lst+2*n,x+2*n);
                add(x+3*n,lst+3*n);
                add(lst+2*n,x);
                add(x+n,lst+3*n);
            }
            lst=x;
        }
    }
    for(int i=1;i<=4*n;i++)
        if(!dfn[i])
            dfs(i);
    for(int i=1;i<=n;i++)
        if(bl[i]==bl[i+n]||bl[i+2*n]==bl[i+3*n]){//这里也可以只判断其中一对,但我不知道这是为什么,或许需要感性理解一下
            cout<<"NIE";
            return 0;
        }
    cout<<"TAK\n";
    //QOJ 需输出方案
    for(int i=1;i<=n;i++)if(bl[i+n]<bl[i])ans[pos[i]]=i;
    for(int i=1;i<=n;i++)if(!ans[pos[i]])ans[pos[i]]=i;
    for(int i=1;i<=k;i++)cout<<ans[i]<<" ";
    return 0;
}
posted @ 2026-09-04 14:29  cqbzcjh  阅读(2)  评论(0)    收藏  举报