Problem Description
小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头。
—— 余光中

集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。

Input
第一行有两个整数,T和M,1<=T<=1000表示队伍数,1<=M<=5000表示对数。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。

Output
可行输出yes,否则输出no,以EOF为结束。

Sample input
1 2
0 1 2
0 1
1 2

2 4
0 1 2
3 4 5
0 3
0 4
1 3
1 4

Sample output
yes
no

图论-2—SAT

本题注意逆否命题边的建立

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e4;
int h[N],e[N],ne[N],idx;
int ch[N],ce[N],cne[N],cidx;
int f[N],vis[N],q[N],cnt;
void add(int u,int v)
{
    e[++idx]=v;
    ne[idx]=h[u];
    h[u]=idx;
}
void cadd(int v,int u)
{
    ce[++cidx]=v;
    cne[cidx]=ch[u];
    ch[u]=cidx;
}
void dfs1(int x)
{
    vis[x]=1;
    for(int i=h[x];~i;i=ne[i])
    {
        int j=e[i];
        if(!vis[j]) dfs1(j);
    }
    q[++cnt]=x;
}
void dfs2(int x,int y)
{
    vis[x]=0;f[x]=y;
    for(int i=ch[x];~i;i=cne[i])
    {
        int j=ce[i];
        if(vis[j]) dfs2(j,y);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    while(cin>>n>>m)
    {
    int T=3*n;
    memset(h,-1,sizeof h);
    memset(ch,-1,sizeof ch);
    idx=0,cnt=0;cidx=0;
    
    for(int i=1;i<=n;++i)
    {
        int a,b,c;
        cin>>a>>b>>c;
        a++;b++;c++;
        add(a,b+T);add(a,c+T);
        add(a+T,b);add(a+T,c);
        add(b,a+T);add(b,c);
        add(b+T,c+T);add(b+T,a);
        add(c,a+T);add(c,b);
        add(c+T,b+T);add(c+T,a);
        cadd(a,b+T);cadd(a,c+T);
        cadd(a+T,b);cadd(a+T,c);
        cadd(b,a+T);cadd(b,c);
        cadd(b+T,c+T);cadd(b+T,a);
        cadd(c,a+T);cadd(c,b);
        cadd(c+T,b+T);cadd(c+T,a);
    }
    for(int i=0;i<m;++i)
    {
        int a,b;
        cin>>a>>b;
        a++;b++;
        add(a,b+T);add(b,a+T);
        cadd(a,b+T);cadd(b,a+T);
    }
    for(int i=1;i<=n*6;++i)
    {
        if(!vis[i]) dfs1(i);
    }
    for(int i=n*6;i;--i)
    {
        if(vis[q[i]]) dfs2(q[i],q[i]);
    }
    bool ans=1;
    for(int i=1;i<=n*3;++i)
    {
        if(f[i]==f[i+T]) 
        ans=0;
    }
    if(ans) cout<<"yes"<<'\n';
    else cout<<"no"<<'\n';
    }
}
 posted on 2023-05-15 20:17  ruoye123456  阅读(21)  评论(0)    收藏  举报