POJ 3905 Perfect Election (2-SAT 判断可行)

题意:有N个人参加选举,有M个条件,每个条件给出:i和j竞选与否会只要满足二者中的一项即可。问有没有方案使M个条件都满足。
分析:读懂题目即可发现是2-SAT的问题。因为只要每个条件中满足2个中的一个即可,因此将人i拆成 点i表示不竞选,和点i+N表示竞选,根据合取式的满足条件建图跑Tarjan。
最后检查每个i与i+N是否在同一强连通分量中。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn =2e3+5;
const int maxm = 2e6+5;
struct Edge{
    int v,next;  
}edges[maxm];
int head[maxn],tot;
stack<int> S;
int pre[maxn],low[maxn],sccno[maxn],dfn,scc_cnt;
void init()
{
    tot = dfn = scc_cnt=0;
    memset(pre,0,sizeof(pre));
    memset(sccno,0,sizeof(sccno));
    memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v)   {
    edges[tot] = (Edge){v,head[u]};
    head[u] = tot++;
}
void Tarjan(int u)
{
    int v;
    pre[u]=low[u]=++dfn;
    S.push(u);
    for(int i=head[u];~i;i=edges[i].next){
        v= edges[i].v;
        if(!pre[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!sccno[v]){
            low[u]=min(low[u],pre[v]);
        }
    }
    if(pre[u]==low[u]){
        int x;
        ++scc_cnt;
        for(;;){
            x = S.top();S.pop();
            sccno[x]=scc_cnt;
            if(x==u)break;
        }
    }    
}

int N,M;

bool check()
{
    int all = 2*N;
    for(int i=1;i<=all;++i){
        if(!pre[i]) Tarjan(i);
    }
    for(int i=1;i<=N;i++){
        if(sccno[i]==sccno[i+N]) return false;
    }
    return true;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    while(scanf("%d %d",&N,&M)==2){
        init();
        int x,y,x1,y1,tmp; char c1,c2;
        for(int i=1;i<=M;++i){
            scanf("
%c%d %c%d",&c1,&x,&c2,&y);
            x1 = x+N,y1 = y+N;      //x1表示x被选
            if(c1=='+' && c2=='+'){
                AddEdge(y,x1), AddEdge(x,y1);
            }
            else if(c1=='+'){
                AddEdge(x,y), AddEdge(y1,x1);
            }
            else if(c2=='+'){
                AddEdge(x1,y1), AddEdge(y,x);
            }
            else{
                AddEdge(x1,y), AddEdge(y1,x);
            }
        }
        if(check()) puts("1");
        else puts("0");
    }
    return 0;
}
为了更好的明天
原文地址:https://www.cnblogs.com/xiuwenli/p/9560620.html