这是我最痛心的一道题,就是少了四句话,忘了加上矛盾而已,导致了我们队的滑铁卢。想想我还是算擅长图论的,这么典型的2-sat题还不过,真的很不应该,面壁……
#include <stdio.h>
#include <cstring>
using namespace std;
struct gtype {
int y,next;
}g[1000100];
int first[20010],tt,n,m,tot,a[10010],x,y,k;
int low[20010],dfn[20010],stk[20010],cnt[20010],id,idx,end;
void add(int x,int y) {
tot++;
g[tot].y=y;
g[tot].next=first[x];
first[x]=tot;
}
void tarjan(int u) {
low[u]=dfn[u]=++idx;
stk[++end]=u;
for(int x=first[u];x!=-1;x=g[x].next) {
int v=g[x].y;
if (!dfn[v]) {
tarjan(v);
if (low[u]>low[v]) low[u]=low[v];
}
else if (cnt[v]==0 && low[u]>dfn[v]) low[u]=dfn[v];
}
if(low[u]==dfn[u]) {
++id;
do {
cnt[stk[end]]=id;
}while(u!=stk[end--]);
}
}
void did(int x,int y,int k) {
int a1=a[x],a2=(a[x]+1)%3;
if (a2==0) a2=3;
int b1=a[y],b2=(a[y]+1)%3;
if (b2==0) b2=3;
if (k==0) {
if (a1==b1) add(x,y),add(y,x),add(x+n,y+n),add(y+n,x+n);
else if (a2==b1) add(x+n,y),add(y,x+n),add(x,x+n),add(y+n,y);
else add(x,y+n),add(y+n,x),add(x+n,x),add(y,y+n);
}
else {
if (a1==b1) add(x,y+n),add(y+n,x),add(y,x+n),add(x+n,y);
else if (a2==b1) add(y,x),add(x+n,y+n);
else add(x,y),add(y+n,x+n);
}
}
int main() {
scanf("%d",&tt);
for (int cas=1;cas<=tt;cas++) {
scanf("%d%d",&n,&m);
tot=0;
memset(g,0,sizeof(g));
memset(first,-1,sizeof(first));
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&x,&y,&k);
if (k==1) did(x,y,1);
else did(x,y,0);
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cnt,0,sizeof(cnt));
id=idx=end=0;
for (int i=1;i<=2*n;i++)
if (!dfn[i]) tarjan(i);
bool yes=true;
for (int i=1;i<=n;i++)
if (cnt[i]==cnt[i+n]) {
yes=false;
break;
}
printf("Case #%d: ",cas);
if (yes) printf("yes\n");
else printf("no\n");
}
return 0;
}