hdu 1814 字典序最小的2sat(暴力深搜)

来源:互联网 发布:淘宝售后是什么 编辑:程序博客网 时间:2024/05/16 16:53
题意:
     题意就是最基础的2sat,关系只有矛盾关系,然后二选一,关键是这个题目是输出字典序最小的那组解。

思路:

     输出字典序最小,用强连通那个实现不了(起码没看到有人实现),其实我们可以直接暴力,我们可以给某个点染色,分成无色(W)红色(R)和蓝色(B)红色是我们要的答案,对于每一个点我们先尽可能的吧他的a染成红色,把他的~a染成蓝色,如果发现矛盾,就是出现a是蓝色的了,那么我们就把当前这个连通块重新清成W吧其实点换成~a这样在继续染色,如果还是不行,那么就证明无解。否则这样全部染完色之后的红色点就是我们要的点。时间复杂度是 n * m * 2,大约也就n * m左右。本以为会超时,感觉到亿了,结果没有,1140ms AC ,貌似是有直接求什么字典序最小的固定算法吧!反正有也不会。哎!

#include<stdio.h>#include<string.h>#include<queue>#define N_node 16000 + 100#define N_edge 40000 + 400#define W 0#define R 1#define B 2using namespace std;typedef struct{   int to ,next;}STAR;STAR E[N_edge];int list[N_node] ,tot;int col[N_node];queue<int>q;void add(int a ,int b){   E[++tot].to = b;   E[tot].next = list[a];   list[a] = tot;}bool DFS(int s){   if(col[s] == B) return 0;   if(col[s] == R) return 1;   col[s] = R ,col[s^1] = B;   q.push(s);   for(int k = list[s] ;k ;k = E[k].next)   if(!DFS(E[k].to)) return 0;   return 1;}bool solve(int n){   memset(col ,W ,sizeof(col));   for(int i = 0 ;i < n ;i ++)   {      if(col[i]) continue;      while(!q.empty()) q.pop();      if(!DFS(i))      {         while(!q.empty())         {            col[q.front()] = col[q.front()^1] = W;            q.pop();         }         if(!DFS(i^1)) return 0;      }   }   return 1;}int main (){   int n ,m ,i ,a ,b;   while(~scanf("%d %d" ,&n ,&m))   {      memset(list ,0 ,sizeof(list)) ,tot = 1;      for(i = 1 ;i <= m ;i ++)      {         scanf("%d %d" ,&a ,&b);         a-- ,b--;         add(a ,b^1) ,add(b ,a^1);      }      if(solve(n * 2))      {         for(i = 1 ;i <= n * 2 ;i ++)         if(col[i-1] == R) printf("%d\n" ,i);      }      else printf("NIE\n");   }   return 0;}

0 0
原创粉丝点击