题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1823

思路

每种材料只能做成满或汉两种方式,因此可以用2-sat简单解决。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn=200;
const int maxm=2000;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

int pre[maxm+10],now[maxn+10],son[maxm+10],tot;
int belong[maxn+10],dfn[maxn+10],low[maxn+10],opp[maxn+10];
int top,stack[maxn+10],k,n,m,cnt,cntl,instack[maxn+10];

inline int trans(char c,int v)
{
  return (v<<1)-(c=='m');
}

inline int ins(int a,int b)
{
  pre[++tot]=now[a];
  now[a]=tot;
  son[tot]=b;
  return 0;
}

int tarjan(int u)
{
  stack[++top]=u;
  instack[u]=1;
  dfn[u]=low[u]=++cnt;
  int j=now[u];
  while(j)
    {
      int v=son[j];
      if(!dfn[v])
        {
          tarjan(v);
          low[u]=std::min(low[u],low[v]);
        }
      else if(instack[v])
        {
          low[u]=std::min(low[u],dfn[v]);
        }
      j=pre[j];
    }
  if(dfn[u]==low[u])
    {
      int w=0;
      ++cntl;
      while(w!=u)
        {
          w=stack[top--];
          instack[w]=0;
          belong[w]=cntl;
        }
    }
  return 0;
}

int main()
{
  k=read();
  while(k--)
    {
      memset(now,0,sizeof now);
      memset(belong,0,sizeof belong);
      memset(dfn,0,sizeof dfn);
      tot=cnt=cntl=0;
      n=read();
      m=read();
      for(int i=1; i<=n; ++i)
        {
          opp[i*2-1]=i*2;
          opp[i*2]=i*2-1;
        }
      for(int i=1; i<=m; ++i)
        {
          char c=getchar();
          while((c<'a')||(c>'z'))
            {
              c=getchar();
            }
          int a=read();
          char d=getchar();
          while((d<'a')||(d>'z'))
            {
              d=getchar();
            }
          int b=read();
          int x=trans(c,a),y=trans(d,b);
          ins(opp[x],y);
          ins(opp[y],x);
        }
      for(int i=1; i<=n<<1; ++i)
        {
          if(!dfn[i])
            {
              tarjan(i);
            }
        }
      int flag=0;
      for(int i=1; i<=n; ++i)
        {
          if(belong[i*2-1]==belong[i*2])
            {
              puts("BAD");
              flag=1;
              break;
            }
        }
      if(!flag)
        {
          puts("GOOD");
        }
    }
  return 0;
}