zoukankan      html  css  js  c++  java
  • [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();
    }
    
    
  • 相关阅读:
    Python 列表元素排重uniq
    Python正则表达式汇总
    Python 正则表达式:只要整数和小数
    c++写入txt文件
    OpenMP求完数
    Python分割list
    用ConfigParser模块读写配置文件——Python
    Python 正则表达式
    教程和工具--用wxPython编写GUI程序的
    matlab 之字体调整
  • 原文地址:https://www.cnblogs.com/mollnn/p/13290614.html
Copyright © 2011-2022 走看看