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 ",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,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 ",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 "); 142 else printf("BAD "); 143 } 144 }