Poj--2749(2-SAT,二分)

2014-10-22 10:55:22

思路:POJ 2-SAT六题完结了。。这题依旧是二分答案,然后2-SAT判断,需要注意的是二分姿势以及每次二分都要重新建图。

  1 /*************************************************************************
  2     > File Name: 2749.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Tue 21 Oct 2014 08:34:43 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 1010;
 27 
 28 int N,AA,BB;
 29 int sx1,sy1,sx2,sy2,sd;
 30 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt;
 31 int low[maxn],dfn[maxn],sc[maxn],scnt,tot;
 32 int x[maxn],y[maxn],A[maxn][2],B[maxn][2];
 33 int s1[maxn],s2[maxn];
 34 stack<int> S;
 35 
 36 void Add_edge(int u,int v){
 37     next[++ecnt] = first[u];
 38     ver[ecnt] = v;
 39     first[u] = ecnt;
 40 }
 41 
 42 void Build_graph(int val){
 43     memset(first,-1,sizeof(first));
 44     ecnt = 0;
 45     for(int i = 0; i < AA; ++i){
 46         Add_edge(A[i][0] * 2,A[i][1] * 2 + 1);
 47         Add_edge(A[i][0] * 2 + 1,A[i][1] * 2);
 48         Add_edge(A[i][1] * 2,A[i][0] * 2 + 1);
 49         Add_edge(A[i][1] * 2 + 1,A[i][0] * 2);
 50     }
 51     for(int i = 0; i < BB; ++i){
 52         Add_edge(B[i][0] * 2,B[i][1] * 2);
 53         Add_edge(B[i][0] * 2 + 1,B[i][1] * 2 + 1);
 54         Add_edge(B[i][1] * 2,B[i][0] * 2);
 55         Add_edge(B[i][1] * 2 + 1,B[i][0] * 2 + 1);
 56     }
 57     for(int i = 0; i < N; ++i){
 58         for(int j = i + 1; j < N; ++j){
 59             if(s1[i] + s1[j] > val){
 60                 Add_edge(i * 2,j * 2 + 1);
 61                 Add_edge(j * 2,i * 2 + 1);
 62             }
 63             if(s1[i] + s2[j] + sd > val){
 64                 Add_edge(i * 2,j * 2);
 65                 Add_edge(j * 2 + 1,i * 2 + 1);
 66             }
 67             if(s2[i] + s1[j] + sd > val){
 68                 Add_edge(i * 2 + 1,j * 2 + 1);
 69                 Add_edge(j * 2,i * 2);
 70             }
 71             if(s2[i] + s2[j] > val){
 72                 Add_edge(i * 2 + 1,j * 2);
 73                 Add_edge(j * 2 + 1,i * 2);
 74             }
 75         }
 76     }
 77 }
 78 
 79 void Dfs(int p){
 80     dfn[p] = low[p] = ++tot;
 81     S.push(p);
 82     for(int i = first[p]; i != -1; i = next[i]){
 83         int v = ver[i];
 84         if(!dfn[v]){
 85             Dfs(v);
 86             low[p] = min(low[p],low[v]);
 87         }
 88         else if(!sc[v]){
 89             low[p] = min(low[p],dfn[v]);
 90         }
 91     }
 92     if(low[p] == dfn[p]){
 93         ++scnt;
 94         while(1){
 95             int x = S.top();
 96             S.pop();
 97             sc[x] = scnt;
 98             if(x == p) break;
 99         }
100     }
101 }
102 
103 void Tarjan(){
104     memset(low,0,sizeof(low));
105     memset(dfn,0,sizeof(dfn));
106     memset(sc,0,sizeof(sc));
107     scnt = tot = 0;
108     while(!S.empty()) S.pop();
109     for(int i = 0; i < 2 * N; ++i)
110         if(!dfn[i]) Dfs(i);
111 }
112 
113 bool Solve(int val){
114     Build_graph(val);
115     Tarjan();
116     //check
117     for(int i = 0; i < 2 * N; i += 2){
118         if(sc[i] == sc[i + 1])
119             return false;
120     }
121     return true;
122 }
123 
124 int main(){
125     int tmax = -1;
126     scanf("%d%d%d",&N,&AA,&BB);
127     scanf("%d%d%d%d",&sx1,&sy1,&sx2,&sy2);
128     sd = abs(sx1 - sx2) + abs(sy1 - sy2);
129     for(int i = 0; i < N; ++i){
130         scanf("%d%d",x + i,y + i);
131         s1[i] = abs(sx1 - x[i]) + abs(sy1 - y[i]);
132         s2[i] = abs(sx2 - x[i]) + abs(sy2 - y[i]);
133         tmax = max(tmax,max(s1[i],s2[i]));
134     }
135     for(int i = 0; i < AA; ++i){
136         scanf("%d%d",&A[i][0],&A[i][1]);
137         --A[i][0];
138         --A[i][1];
139     }
140     for(int i = 0; i < BB; ++i){
141         scanf("%d%d",&B[i][0],&B[i][1]);
142         --B[i][0];
143         --B[i][1];
144     }
145     int ans = -1,mid,l = 0,r = 2 * tmax + sd + 1;
146     while(l < r){
147         mid = getmid(l,r);
148         if(Solve(mid)){
149             ans = mid;
150             r = mid;
151         }
152         else l = mid + 1;
153     }
154     printf("%d\n",ans);
155     return 0;
156 }
157     

 

posted @ 2014-10-22 10:57  Naturain  阅读(115)  评论(0编辑  收藏  举报