zoukankan      html  css  js  c++  java
  • 洛谷P5782 【[POI2001]和平委员会】

    2-SAT问题模板

    先看两道例题:

    【模板】2-SAT 问题

    满汉全席

    在搞懂上面的题后,这题就并不难了。

    最主要的就是跑tarjan和连边。

    比如说:a,b为一个党派,c,d为一个党派,且a,c有仇,那么只能选a,d或b,c。也就是说要在a,d之间连一条边,在b,c之间连一条边。

    上述操作完成后,tarjan跑一边缩点,如果同一个党派的两人在同一个强连通分量里,那么和平委员会就不能创立。~~(别告诉我你连tarjan都不会)~~

    代码如下

    邻接表做法:

    #include<bits/stdc++.h>
    using namespace std;
    vector<int>g[16005];
    stack<int>s;
    int n,m,a,b,ind,cnt,dfn[16005],low[16005],scc[16005],opp[16005],val[16005];
    bool f,vis[16005];
    void tarjan(int u){
        dfn[u]=low[u]=++ind;
        s.push(u);
        vis[u]=1;
        for(int i=0;i<g[u].size();i++){
            int v=g[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(vis[v])low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            cnt++;
            int v;
            do{
                v=s.top();
                s.pop();
                scc[v]=cnt;
                vis[v]=0;
            }while(u!=v);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            g[a].push_back(b&1?b+1:b-1);
            g[b].push_back(a&1?a+1:a-1);
        }
        for(int i=1;i<=n*2;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n*2;i+=2){
            if(scc[i]==scc[i+1]){
                f=1;
                break;
            }
        }
        if(f)printf("NIE");
        else for(int i=1;i<=2*n;i++)if(scc[i]<scc[i&1?i+1:i-1])printf("%d
    ",i);
    }

     前向星做法:

    #include<bits/stdc++.h>
    using namespace std;
    struct edge{
        int next,to;
    }ed[32005];
    stack<int>s;
    int n,m,a,b,num,head[16005],ind,cnt,dfn[16005],low[16005],scc[16005],opp[16005],val[16005];
    bool f,vis[16005];
    void add(int u,int v){
        num++;
        ed[num].to=v;
        ed[num].next=head[u];
        head[u]=num;
    }
    void tarjan(int u){
        dfn[u]=low[u]=++ind;
        s.push(u);
        vis[u]=1;
        for(int i=head[u];i;i=ed[i].next){
            int v=ed[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(vis[v])low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            cnt++;
            int v;
            do{
                v=s.top();
                s.pop();
                scc[v]=cnt;
                vis[v]=0;
            }while(u!=v);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            add(a,b&1?b+1:b-1);
            add(b,a&1?a+1:a-1);
        }
        for(int i=1;i<=n*2;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n*2;i+=2){
            if(scc[i]==scc[i+1]){
                f=1;
                break;
            }
        }
        if(f)printf("NIE");
        else for(int i=1;i<=2*n;i++)if(scc[i]<scc[i&1?i+1:i-1])printf("%d
    ",i);
    }
    对比:邻接表占空间少,但比较慢;前向星占空间多,但比较快。反正都能过
  • 相关阅读:
    转:不在同一个服务器上的数据库之间的数据操作(oracle/sql server的对比)
    即将来到: CSS Feature Queries (CSS特性查询)
    HTML5 Canvas(画布)实战编程初级篇:基本介绍和基础画布元素
    jQuery animate方法开发极客标签Logo动画融合效果
    Bootstrap3实现的响应式幻灯滑动效果个人作品集/博客网站模板
    无需编码开发快速设计互动式UI
    免费资源:Bootstrap开发的创意模板
    通过Intel XDK编写跨平台app(二)
    免费图标:30个食品相关的图标
    CSS中:before和:after选择器的用法
  • 原文地址:https://www.cnblogs.com/gzezzry/p/12109197.html
Copyright © 2011-2022 走看看