题意:
2个人玩石头剪刀布
A和B
n轮 m个约束条件(对A的约束)
下面n个数字表示B的出发 (1为石头 2为布 3为剪刀)
下面m行表示约束条件
u v papa
papa = 1 表示 u v轮 A必须出一样 =0 表示u v轮必须出不一样
问A能否全胜
把一轮拆成: 出0 2 4的方法和 不出 1 3 5的方法
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#define ll int
using namespace std;
inline ll Max(ll a,ll b){return a>b?a:b;}
inline ll Min(ll a,ll b){return a<b?a:b;}
#define N 10010*12
#define M 10010*50
struct Edge{
int to, nex;
}edge[M];
int head[N], edgenum;
void addedge(int u, int v){
Edge E = {v, head[u]};
edge[edgenum] = E;
head[u] = edgenum ++;
}
bool mark[N];
int Stack[N], top;
void init(){
memset(head, -1, sizeof(head)); edgenum = 0;
memset(mark, 0, sizeof(mark));
}
bool dfs(int x){
if(mark[x^1])return false;//一定是拆点的点先判断
if(mark[x])return true;
mark[x] = true;
Stack[top++] = x;
for(int i = head[x]; i != -1; i = edge[i].nex)
if(!dfs(edge[i].to)) return false;
return true;
}
bool solve(int n){
for(int i = 0; i < n; i+=2)
if(!mark[i] && !mark[i^1])
{
top = 0;
if(!dfs(i))//dfs(i) 假设i成立
{//当i不成立时,把所有因i成立的点都取消标记
while( top ) mark[ Stack[--top] ] = false;
if(!dfs(i^1))
return false;//若i的对立面也不成立则i点无解
}
}
return true;
}
int main(){
int n, i, j, k, m, t, Cas = 1; scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
init();
for(i = 0; i < n; i++)
{
addedge(6*i, 6*i+3);
addedge(6*i, 6*i+5);
addedge(6*i+2, 6*i+1);
addedge(6*i+2, 6*i+5);
addedge(6*i+4, 6*i+1);
addedge(6*i+4, 6*i+3);
int hehe;
scanf("%d",&hehe);
if(hehe == 1)
{
addedge(6*i+3, 6*i+0); //不出布一定出石头
addedge(6*i+1, 6*i+2);//不出石头一定出布
}
if(hehe == 2)
{
addedge(6*i+3, 6*i+4);
addedge(6*i+5, 6*i+2);
}
if(hehe == 3)
{
addedge(6*i+5, 6*i+0);
addedge(6*i+1, 6*i+4);
}
}
while(m--)
{
int u, v, papa;
scanf("%d %d %d",&u,&v,&papa); u--, v--;
if(papa == 0)
{
addedge(6*u+0, 6*v+0);
addedge(6*u+4, 6*v+4);
addedge(6*u+2, 6*v+2);
addedge(6*v+0, 6*u+0);
addedge(6*v+4, 6*u+4);
addedge(6*v+2, 6*u+2);
}
else
{
addedge(6*u+0, 6*v+1);
addedge(6*u+2, 6*v+3);
addedge(6*u+4, 6*v+5);
addedge(6*v+0, 6*u+1);
addedge(6*v+2, 6*u+3);
addedge(6*v+4, 6*u+5);
}
}
if(solve(n*12))
printf("Case #%d: yes\n",Cas++);
else
printf("Case #%d: no\n",Cas++);
}
return 0;
}
/*
2
0 4
4 0
3
0 1 24
1 0 86
24 86 0
HDU 4115 必过
*/