HDU 3062 Party(2-sat 模板题 tarjan )

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3062

Problem 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

Source

2009 Multi-University Training Contest 16 - Host by NIT

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;
#define M 4000017
#define N 100017
//a<<1 和 (a<<1) + 1。a<<1表示妻子,(a<<1) + 1表示丈夫
//连接某边是为了推出矛盾。x->y表示选x则必须选y
//注意方向
struct node
{
    int s, t;
    int nxt;
} e[M];
int n, m;
int idx, ans, tp, cont;
int dfn[N],vis[N],low[N],head[N],st[N],belong[N];

void add(int s,int t)
{
    e[cont].s = s;
    e[cont].t = t;
    e[cont].nxt = head[s];
    head[s] = cont++;
}
void build_grap(int a, int b, int c, int d)//建图
{
    if(c==0 && d==0)//两个妻子
    {
        add(a<<1, (b<<1)+1);
        add(b<<1, (a<<1) + 1);
    }
    else if(c==0 && d==1)//妻子和丈夫
    {
        add((a<<1), (b<<1));
        add((b<<1)+1, (a<<1)+1);
    }
    else if(c==1 && d==0)//丈夫和妻子
    {
        add((a<<1) + 1, (b<<1) + 1);
        add(b<<1, a<<1);
    }
    else if(c==1 && d==1)//两个丈夫有矛盾
    {
        add((a<<1)+1, b<<1);
        add((b<<1)+1, a<<1);
    }
}
void tarjan(int u)
{
    dfn[u] = low[u] = ++idx;
    vis[u] = 1;
    st[++tp] = u;
    int v ;
    for(int i = head[u]; i != -1; i = e[i].nxt)
    {
        v = e[i].t ;
        if(!dfn[v])
        {
            tarjan(v) ;
            low[u] = min(low[u],low[v]);
        }
        else if(vis[v])
            low[u] = min(low[u],dfn[v]);
    }
    if(dfn[u] == low[u])
    {
        ans++;
        while(1)
        {
            v = st[tp--];
            vis[v] = 0;
            belong[v] = ans;
            if(v == u)
                break;
        }
    }
}
bool _2sat()
{
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
    idx = tp = ans = 0;
    for(int i = 0; i < 2*n; i++)
        if(!dfn[i])
            tarjan(i) ;
    for(int i = 0; i < n; i++)
        if(belong[2*i]==belong[(2*i)^1])//矛盾
            return false ;
    return true;
}

int main()
{
    int a, b, c, d;
    while(~scanf("%d%d",&n,&m))
    {
        cont = 0;
        memset(head,-1,sizeof(head));
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            //int u, v;
            //u = a*2+c; v = b*2+d;
            //add(u, v^1); add(v, u^1);
            build_grap(a, b, c, d);
        }
        if(_2sat())
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0 ;
}
时间: 2024-11-15 20:17:51

HDU 3062 Party(2-sat 模板题 tarjan )的相关文章

HDU 4085 斯坦纳树模板题

Dig The Wells Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 971    Accepted Submission(s): 416 Problem Description You may all know the famous story "Three monks". Recently they find som

hdu 2085 数塔 -- dp模板题

数塔 Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 已经告诉你了,这是个DP的题目,你能AC吗? Input 输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内. Outp

HDU 5521.Meeting 最短路模板题

Meeting Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 3361    Accepted Submission(s): 1073 Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer Jo

HDU 2222(AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题思路: AC自动机模板题. 一开始使用LRJ的坑爹静态模板,不支持重复的模式串. 在做AC自动机+DP的时候,扒了zcwwzdjn大神的动态优化(失配指向root)写法,以及借鉴了网上的AC自动机模板, 搞出了这么一个支持重复串的模板. #include "cstdio" #include

hdu 2844 Coins 多重背包模板题 ,二进制优化。据说是楼教主的男人八题之一

Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8052    Accepted Submission(s): 3291 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

hdu 1348 Wall(凸包模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1348 Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3386    Accepted Submission(s): 968 Problem Description Once upon a time there was a gre

HDU 1233 prim kruskal最小生成树模板题

A - 还是畅通工程 Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. Input 测试输入包含若干测试

【01背包】HDU 2602 Bone Collector (模板题)

Problem Description Many years ago , in Teddy's hometown there was a man who was called "Bone Collector". This man like to collect varies of bones , such as dog's , cow's , also he went to the grave -The bone collector had a big bag with a volum

HDU 3359 高斯消元模板题,

http://acm.hdu.edu.cn/showproblem.php?pid=3359 题目的意思是,由矩阵A生成矩阵B的方法是: 以a[i][j]为中心的,哈曼顿距离不大于dis的数字的总和 / 个数,就是矩阵B的b[i][j] 现在给出B,要求A 那么我们设A矩阵为a[1][1], a[1][2], a[1][3]..... 那么对于每一个b[i][j]我们有b[i][j] = (a[1][1] + a[1][2] + ... + ) / cnt 所以这样可以建议一条方程,然后guas