• hdu3715 二分+2sat+建图


    题意:
          给你一个递归公式,每多一层就多一个限制,问你最多能递归多少层。
    思路:
         先分析每一层的限制 x[a[i]] + x[b[i]] != c[i],这里面x[] = 0,1,c[i] = 0,1,2

    如果我们把 x[]=0,1想成取或不取,就是基础的关系,那么这个题目就可以直接抽象成2sat问题,然后我们二分去枚举深度,每次根据2sat的结果判断二分走向,我的2sat用的是双深搜的强连通,用那个t打头的也行,随意,这样这个题目就ok了,对了下面总结下2sat的建图吧,这个题目也能用上。


    #include<stdio.h>
    #include<string.h>
    #include<stack>
    
    #define N_node 500 + 10
    #define N_edge 100000 + 100
    
    using namespace std;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    STAR E1[N_edge] ,E2[N_edge];
    int list1[N_node] ,list2[N_node] ,tot;
    int Belong[N_node] ,cnt;
    int mark[N_node];
    int A[11000] ,B[11000] ,C[11000];
    stack<int>st;
    
    void add(int a ,int b)
    {
       E1[++tot].to = b;
       E1[tot].next = list1[a];
       list1[a] = tot;
       
       E2[tot].to = a;
       E2[tot].next = list2[b];
       list2[b] = tot;
    }
    
    void DFS1(int s)
    {
       mark[s] = 1;
       for(int k = list1[s] ;k ;k = E1[k].next)
       if(!mark[E1[k].to]) DFS1(E1[k].to);
       st.push(s);
    }
    
    void DFS2(int s)
    {
       mark[s] = 1;
       Belong[s] = cnt;
       for(int k = list2[s] ;k ;k = E2[k].next)
       if(!mark[E2[k].to]) DFS2(E2[k].to);
    }
    
    bool ok(int mid ,int n)
    {
       memset(list1 ,0 ,sizeof(list1));
       memset(list2 ,0 ,sizeof(list2));
       tot = 1;
       for(int i = 1 ;i <= mid ;i ++)
       {
          int x = A[i] * 2 ,xx = A[i] * 2 + 1;
          int y = B[i] * 2 ,yy = B[i] * 2 + 1;
          if(C[i] == 0) add(xx ,y) ,add(yy ,x);
          if(C[i] == 1) add(x ,y) ,add(y ,x) ,add(xx ,yy) ,add(yy ,xx);
          if(C[i] == 2) add(y ,xx) ,add(x ,yy);
       }
       memset(mark ,0 ,sizeof(mark));
       while(!st.empty()) st.pop();
       for(int i = 0 ;i < n * 2 ;i ++)
       if(!mark[i]) DFS1(i);
       memset(mark ,0 ,sizeof(mark));
       cnt = 0;
       while(!st.empty())
       {
          int xin = st.top();
          st.pop();
          if(mark[xin]) continue;
          cnt ++;
          DFS2(xin);
       }
       int mk = 0; 
       for(int i = 0 ;i < n * 2 && !mk ;i += 2)
       if(Belong[i] == Belong[i^1]) mk = 1;
       return !mk;
    }
    
    int main ()
    {
       int t ,n ,m ,i;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d %d" ,&n ,&m);
          for(i = 1 ;i <= m ;i ++)
          scanf("%d %d %d" ,&A[i] ,&B[i] ,&C[i]);
          int low ,mid ,up ,ans = 0;
          low = 0 ,up = m;
          while(low <= up)
          {
             mid = (low + up) >> 1;
             if(ok(mid ,n))
             ans = mid ,low = mid + 1;
             else up = mid - 1;
          }
          printf("%d
    " ,ans);
       }
       return 0;
    }
          
    

  • 相关阅读:
    波松分酒问题 C++求最优解. Anthony
    Effective STL 条款7 Anthony
    Effective STL 条款16 Anthony
    数据库设计经验之谈[转载]
    C#递归在dropdownlist显示树状
    多域名同主机js转向
    ASP.NET中常用的26个优化性能方法
    域名解析、子域名、cname别名指向、MX记录、泛域名与泛解析、域名绑定、域名转向
    C#数据库递归构造treeview树形结构
    ASP.NET多种方式生成高质量缩略图
  • 原文地址:https://www.cnblogs.com/csnd/p/12063015.html
Copyright © 2020-2023  润新知