HDU 4115 2-sat 石头剪刀布 拆点+约束

来源:互联网 发布:360彩票源码 编辑:程序博客网 时间:2024/04/30 18:24

题意:

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


 

原创粉丝点击