BZOJ1823[JSOI2010]满汉全席

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

首先我们看到这道题目描述里就非常明显地给出了对于每一个点只有两个选择。。。

那么OI中,涉及这种类型的题目一般用什么呢?

2-SAT或是二分图

仔细一看,不像是二分图

于是就是2-SAT

我们可以明显地用贪心的思想,既然他只要评委两样中符合一样就行了

那我们不妨令这两个选择是相斥的

连边+Tarjan

最后判断同一组的点是否属于同一个联通块

如果是,就不合法

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #define ll long long
  7 #define fo(i,x,y) for(int i=x; i<=y; i++)
  8 #define pr(i,x,y) for(int i=x; i>=y; i--)
  9 #define clear(a,x) memset(a,x,sizeof(a))
 10 #define INF 1e9
 11 #define EPS 1e-8
 12 #define LiQin 1 > 0
 13 
 14 using namespace std;
 15 
 16 int N,M;
 17 int mark[200005];
 18 int head1[100005],vet[4000005],next1[4000005];
 19 bool flag[100005];
 20 int top,num;
 21 int cnt;
 22 int Time;
 23 int dfn[100005],low[100005];
 24 int Stack[2000005];
 25 
 26 inline ll read()
 27 { 
 28     int f=1;
 29     ll Tmp=0;
 30     char ch=getchar();
 31     while (ch != '-' && ch < '0' || ch > '9')
 32     {
 33         ch=getchar();
 34     }
 35     if (ch == '-')
 36     {
 37         f=-1;
 38         ch=getchar();
 39     }
 40     while (ch >= '0' && ch <= '9')
 41     {
 42         Tmp=Tmp * 10 + ch - 48;
 43         ch=getchar();
 44     }
 45     return Tmp * f;
 46 }
 47 
 48 void add(int u,int v)
 49 {
 50     vet[++num]=v;
 51     next1[num]=head1[u];
 52     head1[u]=num;
 53 }
 54 
 55 void Tarjan(int u)
 56 {
 57     low[u]=dfn[u]=++Time;
 58     Stack[++top]=u;
 59     flag[u]=1;
 60     for (int e=head1[u]; e != -1; e=next1[e])
 61     {
 62         int V=vet[e];
 63         //printf("%d %d\n",u,V);
 64         if (! dfn[V])
 65         {
 66             Tarjan(V);
 67             low[u]=min(low[u],low[V]);
 68         }
 69         else if (flag[V])
 70         {
 71             low[u]=min(dfn[V],low[u]);
 72         }
 73     }
 74     if (low[u] == dfn[u])
 75     {
 76         cnt++;
 77         while (1)
 78         {
 79             int V=Stack[top--];
 80             flag[V]=0;
 81             mark[V]=cnt;
 82             if (V == u)
 83             {
 84                 break;
 85             }
 86         }
 87     }
 88 }
 89 
 90 int get1()
 91 {
 92     int X;
 93     char c=getchar();
 94     while (c != 'm' && c != 'h')
 95     {
 96         c=getchar();
 97     }
 98     if (c == 'm') X=(read() - 1) * 2;
 99     else X=(read() - 1) * 2 + 1;
100     return X;
101 }
102 
103 int main()
104 {
105     int _=read();
106     while (_--)
107     {
108         scanf("%d%d",&N,&M);
109         //printf("%d %d\n",N,M);
110         num=0;
111         clear(head1,-1);
112         fo(i,1,M)
113         {
114             int u=get1();
115             int v=get1();
116             //printf("%d %d\n",u,v);
117             add(v,u ^ 1);
118             add(u,v ^ 1);
119         }
120         clear(dfn,0);
121         clear(flag,0);
122         clear(low,0);
123         clear(mark,0);
124         top=cnt=Time=0;
125         fo(i,0,2 * N - 1)
126         {
127             if (! dfn[i])
128             {
129                 Tarjan(i);
130             }
131         }
132         bool flag1=true;
133         for (int i=0; i<=2 * N - 2; i+=2)
134         {
135             if (mark[i] == mark[i + 1])
136             {
137                 flag1=false;
138                 break;
139             }
140         }
141         if (flag1) printf("GOOD\n");
142         else printf("BAD\n");
143     }
144 }
Show My Ugly Code

 

posted @ 2017-08-29 21:02  雒煜翾  阅读(145)  评论(0编辑  收藏  举报