2sat题目,正确理解2sat即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=(1e4+9)*2;
int n,m;
int a[maxn][2];
int dfn[maxn],low[maxn],stack[maxn],instack[maxn],s[maxn],un[maxn];
int count,top,con;
int head[maxn<<1],lon;
struct
{
int next,to;
}e[maxn*100];
void edgeini()
{
memset(head,-1,sizeof(head));
lon=-1;
}
void edgemake(int from,int to)
{
e[++lon].to=to;
e[lon].next=head[from];
head[from]=lon;
}
void make(int from,int tmp,int to)
{
if(a[from][tmp]==a[to][0])
edgemake(from*2-tmp,to*2);
else if(a[from][tmp]==a[to][1])
edgemake(from*2-tmp,to*2-1);
else edgemake(from*2-tmp,from*2-(tmp^1));
}
void built(int from,int tmp,int to)
{
if(a[from][tmp]==a[to][0])
edgemake(from*2-tmp,to*2-1);
else if(a[from][tmp]==a[to][1])
edgemake(from*2-tmp,to*2);
}
void tarjan(int t)
{
dfn[t]=low[t]=++count;
instack[t]=1;
stack[++top]=t;
for(int k=head[t];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(dfn[u]==-1)
{
tarjan(u);
low[t]=min(low[t],low[u]);
}
else if(instack[u])
low[t]=min(low[t],dfn[u]);
}
if(dfn[t]==low[t])
{
++con;
while(1)
{
int u=stack[top--];
instack[u]=0;
s[u]=con;
if(u==t) break;
}
}
}
void tarjan()
{
memset(dfn,-1,sizeof(dfn));
memset(instack,0,sizeof(instack));
count=top=con=0;
for(int i=1;i<=n+n;i++)
if(dfn[i]==-1)
tarjan(i);
}
bool chk()
{
for(int i=1;i<=n+n;i+=2)
if(s[i]==s[i+1])
return false;
return true;
}
void solve()
{
tarjan();
bool ans=chk();
if(ans) printf("yes\n");
else printf("no\n");
}
int main()
{
// freopen("in.txt","r",stdin);
int T,cas=0;
scanf("%d",&T);
while(T--)
{
edgeini();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i][0]);
if(a[i][0]==3) a[i][1]=1;
else a[i][1]=a[i][0]+1;
}
for(int k=1,from,to,w;k<=m;k++)
{
scanf("%d%d%d",&from,&to,&w);
if(w==0)
{
make(from,0,to);
make(from,1,to);
make(to,0,from);
make(to,1,from);
}
else
{
built(from,0,to);
built(from,1,to);
built(to,0,from);
built(to,1,from);
}
}
printf("Case #%d: ",++cas);
solve();
}
return 0;
}