【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=4115
【题目大意】
Bob和Alice玩剪刀石头布,一个玩n轮,Alice已经知道了Bob每次要出什么,
1代表剪刀,2代表石头,3代表布,然后Bob对Alice作出了一些限制:
给m行,每行是a b k,如果k是0,表示Alice第a次和b次出的拳必须相同,
如果k是1,表示Alice第a次和b次出的拳必须不相同。
一但Alice破坏了这个限制规则,或者输了一局,那么Alice就彻底输了。问Alice可不可能赢?
【分析】
因为Alice一次都不能输,所以根据Bob出的拳,Alice只可以赢或者平局,即每次有两种选择,是2-SAT模型
然后会有一些矛盾对,假设第a次可以出a1,a2, 第b次可以出b1和b2
如果第a次和b次要求相同, 但是a1和b1不同,说明这个矛盾,建立连接 a1—>b2, b1—>a2.
(a1与b1不同时最多有4种可能的情况需要考虑)
同理,第a次和b次要求不相同,但是a1和b2相同,说明这个矛盾,建立链接a1—>b1, b2—>a2
所以一共有八种情况需要考虑
【代码】
#include<iostream>
#include<cstring>
#include<stack>
#include<iomanip>
#include<cmath>
#include<queue>
#include<algorithm>
#include<stdio.h>
using namespace std;
# define ll long long
#define eps 1e-5
const int maxn=20010;
int a[maxn],b[maxn],c[maxn];
int op[maxn],vis[maxn],low[maxn],dfn[maxn];
int pt[maxn],stk[maxn],color[maxn],pos[maxn],deg[maxn];
vector<int>vc[100100],vc2[100100];
int n,m,sig,cnt,tot,cont;
void add(int x,int y){
vc[x].push_back(y);
}
void top(){
memset(pt,0,sizeof(pt));
queue<int>s;
for(int i=1;i<=sig;i++){
if(deg[i]==0) s.push(i);
}
while(!s.empty()){
int u=s.front();
if(pt[u]==0){
pt[u]=1;
pt[pos[u]]=2;
}
s.pop();
for(int i=0;i<vc2[u].size();i++){
int v=vc2[u][i];
deg[v]--;
if(deg[v]==0) s.push(v);
}
}
cont=0;
for(int i=1;i<=n;i++) {
if(pt[color[i]]==1) op[cont++]=i;
}
}
void tarjan(int u){
vis[u]=1;
dfn[u]=low[u]=cnt++;
stk[++tot]=u;
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i];
if(vis[v]==0) tarjan(v);
if(vis[v]==1) low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u]) {
sig++;
do{
vis[stk[tot]]=-1;
color[stk[tot]]=sig;
}while(stk[tot--]!=u);
}
}
void init(){
sig=0;cnt=1;tot=-1;
memset(deg,0,sizeof(deg));
memset(stk,0,sizeof(stk));
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
for(int i=0;i<maxn;i++) {
vc[i].clear();
vc2[i].clear();
}
}
int solve(){
for(int i=1;i<=n*2;i++) {
if(vis[i]==0) tarjan(i);
}
for(int i=1;i<=n;i++) {
if(color[i]==color[i+n]) return 0;
pos[color[i]]=color[i+n];
pos[color[i+n]]=color[i];
}
for(int i=1;i<=n*2;i++){
for(int j=0;j<vc[i].size();j++){
int v=vc[i][j];
if(color[i]!=color[v]){
deg[color[i]]++;
vc2[color[v]].push_back(color[i]);
}
}
}
top();
return 1;
}
int bob[maxn],bt[4]={0,2,3,1};
int main()
{
int cas;
scanf("%d",&cas);
int kc;
for(kc=1;kc<=cas;kc++)
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
bob[i]=x;
bob[i+n]=bt[x];
}
for(int i=1;i<=m;i++)
{
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
if(k==0)
{
if(bob[a]!=bob[b])
{
add(a,b+n);
add(b,a+n);
}
if(bob[a]!=bob[b+n])
{
add(a,b);
add(b+n,a+n);
}
if(bob[a+n]!=bob[b])
{
add(a+n,b+n);
add(b,a);
}
if(bob[a+n]!=bob[b+n])
{
add(a+n,b);
add(b+n,a);
}
}
else
{
if(bob[a]==bob[b])
{
add(a,b+n);
add(b,a+n);
}
if(bob[a]==bob[b+n])
{
add(a,b);
add(b+n,a+n);
}
if(bob[a+n]==bob[b])
{
add(a+n,b+n);
add(b,a);
}
if(bob[a+n]==bob[b+n])
{
add(a+n,b);
add(b+n,a);
}
}
}
printf("Case #%d: ",kc);
if(solve())
printf("yes\n");
else
printf("no\n");
}
return 0;
}