[PA2010] Riddle

Description

(n) 个点 (m) 条边的无向图被分成 (k) 个部分。每个部分包含一些点。请选择一些关键点,使得每个部分有一个关键点,且每条边至少有一个端点是关键点。

Solution

2-SAT 建图

(x) 表示 (x) 被选为关键点,(x') 表示 (x) 没有被选为关键点

对于每个部分,维护前缀和,(s_{k,i}) 表示第 (k) 个部分中的前 (i) 个点中有被选为关键点,(s_{k,i}') 亦然

于是连边有

(forall <a,b> in E, a' o b, b' o a)

(s_{k,i} o x_{i+1}' (and rev), x_{i} o s_{k,i} (and rev), s_{k,i} o s_{k,i+1} (and rev))

#include <bits/stdc++.h>
using namespace std;
#define reset(a) memset((a),0,sizeof((a)))
const int N = 16000005;

struct edge{
    int to,next;
}e[N];
int head[N],tot,HEAD[N];
int n,m,cnt,turn[N],belong[N],vis[N];

void make(int x,int y){
    e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
    e[++tot].to=x;e[tot].next=HEAD[y];HEAD[y]=tot;
}
void dfs1(int u){
    int i;
    vis[u]=1;
    for(i=head[u];i;i=e[i].next)
        if(!vis[e[i].to])
            dfs1(e[i].to);
    turn[++cnt]=u;
}
void dfs2(int u){
    belong[u]=cnt;vis[u]=1;
    for(int i=HEAD[u];i;i=e[i].next)
        if(!vis[e[i].to])
            dfs2(e[i].to);
}
void kosaraju(){
    for(int i=1;i<=4*n;i++)
        if(!vis[i])dfs1(i);
    reset(vis);cnt=0;
    for(int i=4*n;i>=1;i--)
        if(!vis[turn[i]])
            cnt++,dfs2(turn[i]);
}
void solve(){
    kosaraju();
    for(int i=1;i<=n;i++)
        if(belong[i]==belong[i+n]){
            cout<<"NIE";return;
        }
    cout<<"TAK
";
}

int k,t;

int id(int i)
{
    return i;
}

int id1(int i)
{
    return n+i;
}

int ids(int i)
{
    return n+n+i;
}

int ids1(int i)
{
    return n+n+n+i;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++)
    {
        int t1,t2;
        cin>>t1>>t2;
        int a=t1,b=t2;
        make(id1(a),id(b));
        make(id1(b),id(a));
    }
    for(int i=1;i<=k;i++)
    {
        cin>>t;
        vector <int> vec;
        int tmp;
        for(int j=0;j<t;j++)
        {
            cin>>tmp;
            vec.push_back(tmp);
        }
        for(int j=0;j<t-1;j++)
        {
            make(ids(vec[j]), id1(vec[j+1]));
            make(id(vec[j+1]), ids1(vec[j]));
            make(id(vec[j]), ids(vec[j]));
            make(ids1(vec[j]),id1(vec[j]));
            make(ids(vec[j]), ids(vec[j+1]));
            make(ids1(vec[j+1]), ids1(vec[j]));
        }
    }
    solve();
}