一、题目
二、解法
因为不能失败,所以只能有两种选择,我们尝试把它转化成 2 − sat 2-\text{sat} 2−sat问题。
先处理出能选的两种出法( a i , b i a_i,b_i ai,bi),考虑 k = 0 k=0 k=0(相同)时候怎么建图:
- 如果 a i ≠ a j a_i\not=a_j ai=aj,连 ( a i , b j ) , ( a j , b i ) (a_i,b_j),(a_j,b_i) (ai,bj),(aj,bi)
- 如果 a i ≠ b j a_i\not=b_j ai=bj,连 ( a i , a j ) , ( b j , b j ) (a_i,a_j),(b_j,b_j) (ai,aj),(bj,bj)
- 如果 b i ≠ a j b_i\not=a_j bi=aj,连 ( b i , b j ) , ( a j , a i ) (b_i,b_j),(a_j,a_i) (bi,bj),(aj,ai)
- 如果 b i ≠ b j b_i\not=b_j bi=bj,连 ( b i , a j ) , ( b j , a i ) (b_i,a_j),(b_j,a_i) (bi,aj),(bj,ai)
k = 1 k=1 k=1的时候改一下判断条件就行了,康康代码。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
const int M = 20005;
int read()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
return num*flag;
}
int T,n,m,tot,Index,cnt,a[M],b[M];
int f[M],dfn[M],low[M],in[M],col[M];
stack<int> st;
struct edge
{
int v,next;
}e[10*M];
void add(int u,int v)
{
e[++tot]=edge{v,f[u]},f[u]=tot;
}
void tarjan(int u)
{
in[u]=1;st.push(u);
dfn[u]=low[u]=++Index;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])
tarjan(v),low[u]=min(low[u],low[v]);
else if(in[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int v=0;cnt++;
do
{
v=st.top();st.pop();
in[v]=0;col[v]=cnt;
}while(v!=u);
}
}
int check(int a,int b,int k)
{
if(k==0) return a!=b;
return a==b;
}
signed main()
{
T=read();
for(int cs=1;cs<=T;cs++)
{
n=read();m=read();
tot=Index=cnt=0;
memset(f,0,sizeof f);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(col,0,sizeof col);
for(int i=1;i<=n;i++)
{
int x=read();
if(x==1) a[i]=2,b[i]=3;
if(x==2) a[i]=1,b[i]=3;
if(x==3) a[i]=1,b[i]=2;
}
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),k=read();
if(check(a[x],a[y],k))
{
add(x,y+n);
add(y,x+n);
}
if(check(a[x],b[y],k))
{
add(x,y);
add(y+n,x+n);
}
if(check(b[x],a[y],k))
{
add(x+n,y+n);
add(y,x);
}
if(check(b[x],b[y],k))
{
add(x+n,y);
add(y+n,x);
}
}
printf("Case #%d: ",cs);
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
if(col[i]==col[i+n])
{
puts("no");
goto In;
}
puts("yes");
In:;
}
}