zoukankan      html  css  js  c++  java
  • POJ 2749 Building roads(2-SAT)

    【题目链接】 http://poj.org/problem?id=2749

    【题目大意】

      给出一些点和两个中转点,两点之间的距离为曼哈顿距离,
      除了中转点之外,其余的点之间不能直接相连,现在有一些限制,
      一类是两个点必须连在同一中转点上以及两个点不能连在同一个中转点上
      问点与点之间的最大值的最小值是多少

    【题解】

      首先我们二分这个答案,然后只要判断在距离限制情况下是否能完成连接即可
      因为只有两个中转站,因此很容易想到这是非此即彼的2-SAT问题,
      对于距离的限制,也同样可以转化成两个点能否连在同一个中转站的条件,
      最后判定scc即可。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring> 
    using namespace std;
    const int MAX_V=10000;
    int V; //顶点数
    vector<int> G[MAX_V]; //图的邻接表表示
    vector<int> rG[MAX_V]; //反向图
    vector<int> vs; //后序遍历
    bool used[MAX_V];
    int cmp[MAX_V]; //所属强连通分量的拓扑序
    void add_edge(int from,int to){
        G[from].push_back(to);
        rG[to].push_back(from);
    } 
    void dfs(int v){
        used[v]=1;
        for(int i=0;i<G[v].size();i++){
            if(!used[G[v][i]])dfs(G[v][i]);
        }vs.push_back(v);
    }
    void rdfs(int v,int k){
        used[v]=1;
        cmp[v]=k;
        for(int i=0;i<rG[v].size();i++){
            if(!used[rG[v][i]])rdfs(rG[v][i],k);
        }
    }
    int scc(){
        memset(used,0,sizeof(used));
        vs.clear();
        for(int v=0;v<V;v++){if(!used[v])dfs(v);}
        memset(used,0,sizeof(used));
        int k=0;
        for(int i=vs.size()-1;i>=0;i--){
            if(!used[vs[i]])rdfs(vs[i],k++);
        }return k;
    }
    const int MAX_N=500; 
    int N,A,B;
    int sx[2],sy[2];
    int ys[MAX_N],xs[MAX_N];
    int dist[MAX_N][2],Dist;
    int R1[MAX_V][2],R2[MAX_V][2];
    int mht_dis(int x1,int y1,int x2,int y2){
        return abs(x2-x1)+abs(y2-y1);
    }
    bool check(const int &d){
        for(int i=0;i<V;i++){
            G[i].clear();
            rG[i].clear();
        }
        for(int i=0;i<N;i++){
            for(int j=i+1;j<N;j++){
                for(int k=0;k<2;k++){
                    if(dist[i][k]+dist[j][k]>d){
                        add_edge(2*i+k,2*j+1-k);
                        add_edge(2*j+k,2*i+1-k);
                    }
                    if(dist[i][k]+dist[j][1-k]+Dist>d){
                        add_edge(2*i+k,2*j+k);
                        add_edge(2*j+1-k,2*i+1-k);
                    }
                }
            }
        }
        for(int i=0;i<A;i++){
            for(int k=0;k<2;k++){
                add_edge(2*R1[i][0]+k,2*R1[i][1]+1-k);
                add_edge(2*R1[i][1]+k,2*R1[i][0]+1-k);
            }
        }
        for(int i=0;i<B;i++){
            for(int k=0;k<2;k++){
                add_edge(2*R2[i][0]+k,2*R2[i][1]+k);
                add_edge(2*R2[i][1]+1-k,2*R2[i][0]+1-k);
            }
        }scc();
        for(int i=0;i<N;i++){
            if(cmp[2*i]==cmp[2*i+1])return 0;
        }return 1;
    }
    int solve(){
        V=2*N;
        Dist=mht_dis(sx[0],sy[0],sx[1],sy[1]);
        for(int i=0;i<N;i++){
            for(int k=0;k<2;k++)dist[i][k]=mht_dis(xs[i],ys[i],sx[k],sy[k]);
        }int max_dist=0;
        for(int i=0;i<N;i++){
            for(int j=i+1;j<N;j++){
                for(int k=0;k<2;k++){
                    max_dist=max(max_dist,dist[i][k]+dist[j][k]);
                    max_dist=max(max_dist,dist[i][k]+dist[j][1-k]+Dist);
                }
            }
        }
        int ans=-1,l=0,r=max_dist;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid-1,ans=mid;
            else l=mid+1;
        }return ans;
    }
    int main(){
    	scanf("%d%d%d",&N,&A,&B);
        for(int i=0;i<2;i++)scanf("%d%d",sx+i,sy+i);
        for(int i=0;i<N;i++)scanf("%d%d",xs+i,ys+i);
        for(int i=0;i<A;i++)for(int k=0;k<2;k++){scanf("%d",R1[i]+k);R1[i][k]--;}
        for(int i=0;i<B;i++)for(int k=0;k<2;k++){scanf("%d",R2[i]+k);R2[i][k]--;}
        printf("%d
    ",solve());
        return 0;
    }
  • 相关阅读:
    HTML DOM教程 14HTML DOM Document 对象
    HTML DOM教程 19HTML DOM Button 对象
    HTML DOM教程 22HTML DOM Form 对象
    HTML DOM教程 16HTML DOM Area 对象
    ubuntu 11.04 问题 小结
    VC6.0的 错误解决办法 小结
    boot.img的解包与打包
    shell里 截取字符串
    从零 使用vc
    Imagemagick 对图片 大小 和 格式的 调整
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2749.html
Copyright © 2011-2022 走看看