2SAT+uva1146

来源:互联网 发布:js在数组的末尾加上空 编辑:程序博客网 时间:2024/05/21 13:59

学习了一下2SAT,以前看不太明白的,现在大概看明白了,顺便敲一下训练指南上的飞机调度问题

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<vector>using namespace std;const int maxn=20100;int n,T[maxn][2];struct twoset{    int n;    vector<int> g[maxn*2];    bool mark[maxn*2];    int S[maxn*2],c;    void init(int n)    {        this->n=n;        memset(mark,0,sizeof(mark));        for(int i=0;i<n*2;i++)g[i].clear();    }    bool dfs(int x)    {        if(mark[x^1])return false;        if(mark[x])return true;        mark[x]=true;        S[c++]=x;        for(int i=0;i<g[x].size();i++)        {            int v=g[x][i];            if(!dfs(v))return false;        }        return true;    }    void add_clause(int x,int vx,int y,int vy)    {        x=x*2+vx;        y=y*2+vy;        g[x^1].push_back(y);        g[y^1].push_back(x);    }    bool solve()    {        for(int i=0;i<n*2;i+=2)        {            if(!mark[i]&&!mark[i+1])            {                c=0;                if(!dfs(i))                {                    while(c>0)mark[S[--c]]=false;                    if(!dfs(i+1))return false;                }            }        }        return true;    }}a;bool can(int mid){   a.init(n);    for(int i=0;i<n;i++)        for(int x=0;x<2;x++)        for(int j=i+1;j<n;j++)        for(int y=0;y<2;y++)        if(abs(T[i][x]-T[j][y])<mid)        a.add_clause(i,x^1,j,y^1);    return a.solve();}int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt","r",stdin);    #endif    while(scanf("%d",&n)!=EOF&&n)    {        int L=0,R=0,mid;        for(int i=0;i<n;i++)            for(int j=0;j<2;j++)            {                cin>>T[i][j];                R=max(R,T[i][j]);            }        while(L<R)        {            mid=L+(R-L+1)/2;            if(can(mid))L=mid;            else R=mid-1;        }        cout<<L<<endl;    }    return  0;}


还可以用tarjan算法(转载)

#include <cstdio>  #include <cstring>  #include <algorithm>  #include <cstdlib>  #include <vector>  #include <stack>  using namespace std;  const int N = 4444;  int pre[N], sccno[N], lowlink[N], dfs_clock, scc_cnt, T[N][2], n;  stack<int> S;  vector<int> G[N];  void add_edge(int x, int xval, int y, int yval){      x = x * 2 + xval;      y = y * 2 + yval;      G[x ^ 1].push_back(y);      G[y ^ 1].push_back(x);  }  void dfs(int u){      pre[u] = lowlink[u] = ++dfs_clock;      S.push(u);      for (int i = 0; i < G[u].size(); i++){          int v = G[u][i];          if (!pre[v]){              dfs(v);              lowlink[u] = min(lowlink[u], lowlink[v]);          }          else if (!sccno[v])              lowlink[u] = min(lowlink[u], pre[v]);      }      if (lowlink[u] == pre[u]){          scc_cnt += 1;          for (;;){              int x = S.top(); S.pop();              sccno[x] = scc_cnt;              if (x == u) break;          }      }  }  void tarjan(int n){      dfs_clock = scc_cnt = 0;      memset(pre, 0, sizeof(pre));      memset(sccno, 0, sizeof(sccno));      memset(lowlink, 0, sizeof(lowlink));      for (int i = 0; i < n; i++)          if (!pre[i]) dfs(i);  }  bool check(int t){      for (int i = 0; i <= 2 * n; i++)          G[i].clear();      for (int i = 0; i < n; i++) for (int a = 0; a < 2; a++)          for (int j = i + 1; j < n; j++) for (int b = 0; b < 2; b++)              if (abs(T[i][a] - T[j][b]) < t) add_edge(i, a ^ 1, j, b ^ 1);      tarjan(n * 2);      //for (int i = 0; i < n * 2; i++) printf("%d ", sccno[i]);      //printf("\n");      for (int i = 0; i < n * 2; i += 2)          if (sccno[i] == sccno[i + 1]) return 0;      return 1;  }  int main(){      while(~scanf("%d", &n) && n){          int l = 0, r = 0;          for (int i = 0; i < n; i++)              for (int j = 0; j < 2; j++){                  scanf("%d", &T[i][j]);                  r = max(r, T[i][j]);              }          while (l < r){              int m = l + (r - l + 1) / 2;              if (check(m)) l = m;              else r = m - 1;          }          printf("%d\n", l);      }      return 0;  }  



0 0
原创粉丝点击