zoukankan      html  css  js  c++  java
  • hdu1815 2sat + 二分 + 建图

    题意:
          给你两个总部,s1 ,s2,和n个点,任意两点之间都是通过这个总部相连的,其中有一些点不能连在同一个总部上,有一些点可以连接在同一个总部上,总部和总部之间可以直接连接,就是假如a,b相连,可以使这样四中情况中的一种
    a-s1  s1 - b
    a-s2  s2 - b
    a-s1  s1 - s2  s2 - b
    a-s2  s2 - s1  s1 - b
    最后问你任意ab距离最远的最近是多少。


    思路:
          首先这个题目的总部有两个,还有一些限制关系,那么很容易就想到2sat问题,关键是怎么建边,怎样找到限制关系,还是举例子说容易懂,
    s_x1[i] : 表示i点到S1的距离。
    s_x2[i] : 表示i点到S2的距离。
    D 表示S1,S2的距离。

    彼此厌恶 x -> ~y ,y -> ~x ,~y -> x ,~x -> y
    彼此喜欢 x -> y ,~x -> ~y ,y -> x ,~y -> ~x


    s_x1[x] + s_x1[y] > mid          x -> ~y ,y -> ~x

    s_x2[x] + s_x2[y] > mid          ~x -> y ,~y -> x
    s_x1[x] + s_x2[y] + D > mid      x -> y ,~y -> ~x
    s_x2[x] + s_x1[y] + D > mid      ~x -> ~y ,y -> x


    每次二分就这么建边就ok了,还有提示下,之前在网上看到有个人的题解是直接先跑了便彼此厌恶和喜欢的,然后二分的时候就不管那个了,那个我感觉正确性说不通,我是每次都全部从新建边的,上面的如果写错了请大家留言指教,互相学习。


    #include<stdio.h>
    #include<string.h>
    #include<stack>
    
    #define N_node 1000 + 10
    #define N_edge 5000000 + 300
    
    using namespace std;
    
    typedef struct
    {
       int to ,next;
    }STAR;
    
    typedef struct
    {
       int x ,y;
    }NODE;
    
    STAR E1[N_edge] ,E2[N_edge];
    NODE S1 ,S2 ,A;
    int s_x1[550] ,s_x2[550];
    int list1[N_node] ,list2[N_node] ,tot;
    int Belong[N_node] ,cnt;
    int mark[N_node];
    int F[1100][2] ,NF[1100][2];
    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);
    }
    
    int abss(int x)
    {
       return x > 0 ? x : -x;
    }
    
    int dis(NODE a ,NODE b)
    {
       return abss(a.x - b.x) + abss(a.y - b.y);
    }
       
    bool ok(int mid ,int n ,int m ,int q)
    {
        memset(list1 ,0 ,sizeof(list1));
        memset(list2 ,0 ,sizeof(list2));
        tot = 1;
        for(int i = 1 ;i <= m ;i ++)
        {
             int x = NF[i][0] * 2 ,xx = NF[i][0] * 2 + 1;
             int y = NF[i][1] * 2 ,yy = NF[i][1] * 2 + 1;
             add(x ,yy) ,add(y ,xx);
             add(yy ,x) ,add(xx ,y);
        }
        for(int i = 1 ;i <= q ;i ++)
        {
             int x = F[i][0] * 2 ,xx = F[i][0] * 2 + 1;
             int y = F[i][1] * 2 ,yy = F[i][1] * 2 + 1;
             add(x ,y) ,add(xx ,yy);
             add(y ,x) ,add(yy ,xx);
        }
        int D = dis(S1 ,S2);
        for(int i = 0 ;i < n ;i ++)
        for(int j = i + 1 ;j < n ;j ++)
        {
            int x = i * 2 ,xx = i * 2 + 1;
            int y = j * 2 ,yy = j * 2 + 1;
            if(s_x1[i] + s_x1[j] > mid) add(x ,yy) ,add(y ,xx);
            if(s_x2[i] + s_x2[j] > mid) add(xx ,y) ,add(yy ,x);
            if(s_x1[i] + s_x2[j] + D > mid) add(x ,y) ,add(yy ,xx);
            if(s_x2[i] + s_x1[j] + D > mid) add(xx ,yy) ,add(y ,x);
        }
        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 n ,m ,q;
       int i ,low ,mid ,up;
       while(~scanf("%d %d %d" ,&n ,&m ,&q))
       {
          scanf("%d %d %d %d" ,&S1.x ,&S1.y ,&S2.x ,&S2.y);
          low = up = 8000000;
          for(i = 0 ;i < n ;i ++)
          {
             scanf("%d %d" ,&A.x ,&A.y);
             s_x1[i] = dis(A ,S1);
             s_x2[i] = dis(A ,S2);
             if(low > s_x1[i]) low = s_x1[i];
             if(low > s_x2[i]) low = s_x2[i];
          }
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d" ,&NF[i][0] ,&NF[i][1]);
             NF[i][0] -- ,NF[i][1] --;
          }
          for(i = 1 ;i <= q ;i ++)
          {
             scanf("%d %d" ,&F[i][0] ,&F[i][1]);
             F[i][0] -- ,F[i][1] -- ;
          }
          int ans = -1;
          while(low <= up)
          {
             mid = (low + up) >> 1;
             if(ok(mid ,n ,m ,q))
             ans = mid ,up = mid - 1;
             else low = mid + 1;
          }
          printf("%d
    " ,ans);
       }
       return 0;
    }
          
    







  • 相关阅读:
    关于c#.net 使用自动生成的TableAdapter类的Insert、update方法无效
    .net 字符流下载 迅雷下载问题
    win7 64位系统下使用Oracle的问题
    使用vs2010发布.net framework2.0的网站出现的 分析器错误
    c博客作业我的第一篇博客
    C博客作业01分支,顺序结构1
    机器学习特训营前四次课总结
    ASP.NET应用程序与页面生命周期
    asp.net 获取文件的详细属性,大小,修改日期,所在位置等
    Json string value cannot have line breaks(解决方法)
  • 原文地址:https://www.cnblogs.com/csnd/p/12063014.html
Copyright © 2011-2022 走看看