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);
    }
    对比:邻接表占空间少,但比较慢;前向星占空间多,但比较快。反正都能过
  • 相关阅读:
    hihoCoder 1398 : 网络流五·最大权闭合子图
    hihoCoder:1394 : 网络流四·最小路径覆盖
    hihoCoder 1393: 网络流三·二分图多重匹配
    hihoCoder1378:网络流二·最大流最小割定理
    hihoCoder1369:网络流一·Ford-Fulkerson算法(FF算法)
    [NOIP2011]铺地毯(贪心)
    hdu 3452:Bonsai(最小割)
    hdu 3549:Flow Problem(最大流)
    (转载)JavaScript中定义变量
    (转载)浅谈javascript的分号
  • 原文地址:https://www.cnblogs.com/gzezzry/p/12109197.html
Copyright © 2011-2022 走看看