• LA3211二分答案+2-sat+总结的此类问题统一建模方法


      1 /*LA3211
      2 2-sat+二分答案
      3 现在统一建模的方式:
      4 1、同一组的两个状态分别存储在2*i和2*i+1两个节点,产生2*n个节点
      5 2、for(int i=1;i<2*n;i++)
      6    for(int j=0;j<i;j++)
      7    {
      8       if (i==(j^1)) continue;
      9       sat.add_clause(i,j);//枚举出的不属于同一组的不相容的两点
     10    }
     11 3、2-sat即可
     12 和HDU3622相似
     13 */
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 #include <math.h>
     18 #include <ctype.h>
     19 #include <string>
     20 #include <iostream>
     21 #include <sstream>
     22 #include <vector>
     23 #include <queue>
     24 #include <stack>
     25 #include <map>
     26 #include <list>
     27 #include <set>
     28 #include <algorithm>
     29 #define INF 0x3f3f3f3f
     30 #define LL long long
     31 #define eps 1e-4
     32 #define maxn 2010
     33 using namespace std;
     34 int T[2*maxn];
     35 struct TwoSAT
     36 {
     37     int n;
     38     vector<int> G[maxn*2];
     39     bool mark[maxn*2];//联系《2-sat算法解析》中的红蓝标色
     40     int S[maxn*2],c;
     41     bool dfs(int x)
     42     {
     43         if (mark[x^1]) return false;//真假同时被标记,逻辑矛盾
     44         if (mark[x]) return true;//x被标记,意味着下面的节点也被标记,思想是记忆化搜索
     45         mark[x]=true;
     46         S[c++]=x;
     47         for(int i=0; i<G[x].size(); i++)
     48         if(!dfs(G[x][i])) return false; //同一个强联通分量应该表上同一种颜色
     49         return true;
     50     }
     51     void init(int n)
     52     {
     53         this->n=n;
     54         for(int i=0; i<n*2; i++) G[i].clear();
     55         memset(mark,0,sizeof(mark));
     56     }
     57     //x=xval or y=xval ,x 则 xval=0,x'则xval=1
     58     void add_clause(int x ,int y)
     59     {
     60         G[x].push_back(y^1);
     61         G[y].push_back(x^1);
     62     }
     63     bool solve()
     64     {
     65         for(int i=0;i<n*2;i+=2)
     66         {
     67             if(!mark[i] && !mark[i^1])//真假都没被标记才需dfs,思考一下,原书上写的是[mark+1],这是由i的取值和步长决定的,这里更改,使逻辑含义统一
     68             {
     69                 c=0;//记得清零
     70                 if(!dfs(i))//将i标记为true
     71                 {
     72                     while(c>0) mark[S[--c]]=false;
     73                     if (!dfs(i^1)) return false;//更改初始标号颜色。只要有一个对象不能“二选一”,则2-sat无解
     74                 }
     75             }
     76         }
     77         return true;
     78     }
     79 } sat;
     80 double dis(double x1,double y1,double x2,double y2)
     81 {
     82     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
     83 }
     84 int n;
     85 bool solve(int time)
     86 {
     87     sat.init(n);
     88     for(int i=1;i<2*n;i++)//枚举
     89     {
     90         for(int j=0;j<i;j++)
     91         {
     92             if (i==(j^1)) continue;//消除所有的同一组的
     93             if (time>abs(T[i]-T[j])) sat.add_clause(i,j);
     94         }
     95     }
     96     return sat.solve();
     97 }
     98 int nextint(){int x;scanf("%d",&x);return x;}
     99 int main()
    100 {
    101     while(cin>>n)
    102     {
    103         for(int i=0;i<n;i++)
    104         {
    105             T[i*2]=nextint();
    106             T[i*2+1]=nextint();
    107         }
    108         int L=0,R=10000001;
    109         while(R>L)
    110         {
    111             int M=(L+R+1)/2;
    112             if (!solve(M)) R=M-1;else L=M;
    113         }
    114         cout<<L<<endl;
    115         //貌似printf不能配合ceil使用 = =~
    116         //最终结果要求是整数,要满足实际意义
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    MySql面试题、知识汇总、牛客网SQL专题练习
    产生过拟合的原因
    《人类简史》这本烧脑书风靡全球的秘密是什么?
    厌食?暴食?试试这个 VR 新疗法
    协程、异步IO
    进程池
    进程(同步)锁
    特朗普变脸:同媒体“友好会谈”,怨媒体“死不悔改”
    多进程Queue
    redis 在 php 中的应用(事务 [ Transaction ] 篇)
  • 原文地址:https://www.cnblogs.com/little-w/p/3585617.html
Copyright © 2020-2023  润新知