hdu 3062 Party

Description

有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
 

Input

n: 表示有n对夫妻被邀请 (n<= 1000) 
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1)) 

在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2 
A1,A2分别表示是夫妻的编号 
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫 
夫妻编号从 0 到 n -1 
 

Output

如果存在一种情况 则输出YES 
否则输出 NO 
 

Sample Input

2 1 0 1 1 1
 

Sample Output

YES
 
一道2—SAT的模板题,其实就是建立一个无向图,然后求强连通分量,再看看同一对夫妻是不是在同一个强连通分量里
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define  inf 0x0f0f0f0f
using namespace std;

struct SCC
{
    static const int maxn=2000+10;
    vector<int>group[maxn],scc[maxn];
    int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt,n,m;
    stack<int>S;

    void init()
    {
        for (int i=0;i<=n;i++) group[i].clear();
    }

    void addedge(int from,int to)
    {
        group[from].push_back(to);
    }

    void dfs(int u)
    {
        pre[u]=lowlink[u]=++dfs_clock;
        S.push(u);
        for (int i=0;i<group[u].size();i++)
        {
            int v=group[u][i];
            if (!pre[v])
            {
                dfs(v);
                lowlink[u]=min(lowlink[u],lowlink[v]);
            }
            else if (!sccno[v])
            {
                lowlink[u]=min(lowlink[u],pre[v]);
            }
        }
        if (lowlink[u]==pre[u])
        {
            scc_cnt++;
            scc[scc_cnt].clear();
            while (1)
            {
                int x=S.top();
                S.pop();
                scc[scc_cnt].push_back(x);
                sccno[x]=scc_cnt;
                if (x==u) break;
            }
        }
    }

    void find_scc()
    {
        dfs_clock=scc_cnt=0;
        memset(pre,0,sizeof(pre));
        memset(sccno,0,sizeof(sccno));
        for (int i=1;i<=n;i++)
        if (!pre[i]) dfs(i);
    }
};

SCC people;

int main()
{
    int N,M,x,y,x1,y1;
    while(scanf("%d",&N)!=EOF)
    {
        people.n=2*N;
        people.init();
        scanf("%d",&M);
        for (int i=1;i<=M;i++)
        {
            scanf("%d%d%d%d",&x,&y,&x1,&y1);
            people.addedge(x*2+x1,(y*2+y1)^1);
            people.addedge(y*2+y1,(x*2+x1)^1);
        }
        people.find_scc();
        bool flag=true;
        for (int i=0;i<2*N;i+=2)
        {
            if (people.sccno[i]==people.sccno[i+1])
            {
                flag=false;
                break;
            }
        }
        if (flag) printf("YES
");
        else printf("NO
");
    }
    return 0;
}

作者 chensunrise

至少做到我努力了
原文地址:https://www.cnblogs.com/chensunrise/p/3776474.html