zoukankan      html  css  js  c++  java
  • POJ2749 Building road

    传送门

    这道题真是2-SAT好题啊!!卡了我两个点才做完……垃圾POJ还不告诉我哪错了……

    首先我们先花一段时间把题看懂……(其实是翻译一下),之后我们发现因为每个谷仓只能向一个中转点连边,所以他就是一个布尔变量的两个取值。然后对于每个限制条件,其实就是^嘛!我们把他转换为合取范式之后建一下图。不过怎么计算最大距离最小值呢?看到这一幕想起二分答案……然后,然后就不会了……

    我们再想一下,其实2-SAT里面,每个给定的限制特别要命,因为如果要没有限制随便瞎取都能合法,然后我们要限制一个最大距离……那我们不妨把连接之后距离大于当前值的两个谷仓加一个限制,使两者不能连边,这样我们再跑一遍2-SAT判断一下当前是否合法,然后改变二分的值就可以。

    具体怎么加距离的限制,如果两个点通过某种连接方式之后不合法,我们就把其中一个向另一个的否定连边(一个点连接s1,s2),比如说第一个点连向s1,第二个点连向s2,如果这样是不合法的情况的话,那么我们强制性让第一个点连s2,第二个点连s1,这样建边就可以啦。

    然而说着容易做着难……代码贼拉难写+忘记判断-1+不知道怎么建边……卡了两个小时。

    Source Code
    Problem: 2749        User: ifvisit
    Memory: 6176K        Time: 1657MS
    Language: C++        Result: Accepted
    
        Source Code
    
        #include<cstdio>
        #include<algorithm>
        #include<cstring>
        #include<iostream>
        #include<cmath>
        #include<set>
        #include<queue>
        #define rep(i,a,n) for(int i = a;i <= n;i++)
        #define per(i,n,a) for(int i = n;i >= a;i--)
        #define fill(x,y) memset(x,y,sizeof(x));
        #define enter putchar('
    ')
    
        using namespace std;
        typedef long long ll;
        const int M = 10005;
        const int N = 500005;
        const int INF = 1000000009;
    
        int read()
        {
            int ans = 0,op = 1;
            char ch = getchar();
            while(ch < '0' || ch > '9')
            {
            if(ch == '-') op = -1;
            ch = getchar();
            }
            while(ch >= '0' && ch <= '9')
            {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
            }
            return ans * op;
        }
    
        struct edge
        {
            int next,to,from;
        }e[N];
    
        struct node
        {
            int x,y;
        }q[M];
    
        struct relation
        {
            int a,b;
        }ha[M],li[M];
    
        int n,m,g,head[M],ecnt,dfn[M],low[M],stack[M],top,scc[M],a,b,c,d,dis1[M],dis2[M],len,idx,cnt;
        int minn = 100000000,maxn,ans;
        int s1 = 2000,s2 = 2001;
        bool vis[M];
    
        void add(int x,int y)
        {
            e[++ecnt].to = y;
            e[ecnt].from = x;
            e[ecnt].next = head[x];
            head[x] = ecnt;
        }
        int rev(int x)
        {
            return x > n ? x - n : x + n;
        }
    
        int mht(int kx,int ky)
        {
            return abs(q[kx].x - q[ky].x) + abs(q[kx].y - q[ky].y);
        }
    
        void clear()
        {
            memset(e,0,sizeof(e));
            memset(head,0,sizeof(head));
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(scc,0,sizeof(scc));
            ecnt = idx = cnt = 0;
        }
    
        void build(int x)
        {
            rep(i,1,m)
            {
            int r1 = ha[i].a,r2 = ha[i].b;
            add(r1,r2+n),add(r1+n,r2),add(r2,r1+n),add(r2+n,r1);
            }
            rep(i,1,g)
            {
            int r1 = li[i].a,r2 = li[i].b;
            add(r1,r2),add(r2,r1),add(r1+n,r2+n),add(r2+n,r1+n);
            }
            rep(i,1,n)
            {
            rep(j,i+1,n)
            {
                int l1 = dis1[i],l2 = dis2[i],r1 = dis1[j],r2 = dis2[j];
                if(l1 + r1 > x) add(i,j+n),add(j,i+n);
                if(l2 + r2 > x) add(i+n,j),add(j+n,i);
                if(l1 + r2 + len > x) add(i,j),add(j+n,i+n);
                if(l2 + r1 + len > x) add(i+n,j+n),add(j,i);
            }
            }
        }
    
        void tarjan(int x)
        {
            dfn[x] = low[x] = ++idx;
            stack[++top] = x,vis[x] = 1;
            for(int i = head[x];i;i = e[i].next)
            {
            if(!dfn[e[i].to]) tarjan(e[i].to),low[x] = min(low[x],low[e[i].to]);
            else if(vis[e[i].to]) low[x] = min(low[x],dfn[e[i].to]);
            }
            if(low[x] == dfn[x])
            {
            int p;
            cnt++;
            while((p = stack[top--]))
            {
                scc[p] = cnt,vis[p] = 0;
                if(p == x) break;
            }
            }
        }
    
        void solve()
        {
            int l = 0,r = 8000000;
            while(l < r)
            {
            bool flag = 0;
            int mid = (l+r) >> 1;
            clear(),build(mid);
            rep(i,1,n<<1) if(!dfn[i]) tarjan(i);
            rep(i,1,n)
            {
                if(scc[i] == scc[i+n])
                {
                flag = 1;
                break;
                }
            }
            if(flag) l = mid + 1;
            else r = mid;
            }
            if(l == 0 || l == 8000000) printf("-1
    ");
            else printf("%d
    ",l);
        }
    
        int main()
        {
            n = read(),m = read(),g = read();
            q[s1].x = read(),q[s1].y = read(),q[s2].x = read(),q[s2].y = read();
            len = abs(q[s2].y-q[s1].y) + abs(q[s2].x-q[s1].x);
            rep(i,1,n)
            {
            q[i].x = read(),q[i].y = read();
            dis1[i] = mht(i,s1),dis2[i] = mht(i,s2);
            }
            rep(i,1,m) ha[i].a = read(),ha[i].b = read();
            rep(i,1,g) li[i].a = read(),li[i].b = read();
            solve();
            return 0;
        }
  • 相关阅读:
    KMP算法与字符串匹配问题
    贪婪算法(贪心算法)
    普里姆算法(Prim)与最小生成树问题
    克鲁斯卡尔算法(Kruskal算法)与最小生成树问题
    Dijkstra算法与最短路径问题
    SpringCloud(十一)使用actuator和dashborad、turbine对微服务进行监控
    博客美化——页面白天黑夜切换
    Spring5学习笔记——day01
    Mybatis学习笔记——day06
    Mybatis学习笔记——day05
  • 原文地址:https://www.cnblogs.com/captain1/p/9761095.html
Copyright © 2011-2022 走看看