题意:
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 必过 */