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;
    }
  • 相关阅读:
    LinkedList的实现源码分析
    ArrayList实现源码分析
    探索HashMap实现原理及其在jdk8数据结构的改进
    Maven的安装使用以及 Maven+Spring hello world example
    RedisHelper帮助类
    Stream 和 byte[] 之间的转换
    WCF For Silverlight跨域策略
    Linq Query常见错误
    Linq to Sharepoint--如何获取Linq Query 生成的CALM
    如何使用代码备份SQL Server数据库
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2749.html
Copyright © 2011-2022 走看看