首页 > 代码库 > POJ 2749

POJ 2749

二分+2SAT的题

写错了HIGH和LOW与MID的变换,TLE了好几次。。

按HATE和LIKE关系先加边,再用距离的限制加边。

dist(i,S1)+dist(S1,j)>limit  Xi->~Xj  Xj->Xi

dist(i,S2)+dist(S2,j)>limit  ~Xi->Xj  ~Xj->Xi

dist(i,S1)+dist(S1,S2)+dist(S2,j)>limit Xi->Xj  ~Xj->~Xi

dist(i,S2)+dist(S2,S1)+dist(S1,j)>limit ~Xi->~Xj  Xj->Xi

用离散数学的知识就能推出来,以上借别人的一用。

  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <algorithm>  5 #include <cmath>  6   7 using namespace std;  8   9 const int inf=8500000; 10 const int MAXN=1050; 11 const int MAXM=20000000; 12 int s1_s2,dis1[MAXN],dis2[MAXN],head[MAXN],dfn[MAXN],low[MAXN],belong[MAXN]; 13 int st[MAXN],stop,indx,tot,pat; 14 bool stack[MAXN]; int leng; 15 int n,hn,ln; 16 struct d{ 17     int x,y; 18 }point[MAXN],s1,s2; 19 struct h{ 20     int u,v; 21 }hate[MAXN*2]; 22 struct l{ 23     int u,v; 24 }like[MAXN*2]; 25  26 struct ei{ 27     int u,v; 28     int next; 29 }edge[MAXM]; 30  31 void addedge(int u,int v){ 32     edge[tot].u=u; 33     edge[tot].v=v; 34     edge[tot].next=head[u]; 35     head[u]=tot++; 36 } 37  38 void tarjan(int u){ 39     int v; 40     dfn[u]=low[u]=++indx; 41     st[stop++]=u; 42     stack[u]=true; 43     for(int e=head[u];e!=-1;e=edge[e].next){ 44         v=edge[e].v; 45         if(dfn[v]==0){ 46             tarjan(v); 47             low[u]=min(low[u],low[v]); 48         } 49         else if(stack[v]){ 50             low[u]=min(low[u],dfn[v]); 51         } 52     } 53     if(dfn[u]==low[u]){ 54         pat++; 55         do{ 56             v=st[--stop]; 57             stack[v]=false; 58             belong[v]=pat; 59         }while(u!=v); 60     } 61 } 62  63 bool slove(){ 64     int u,v; 65      66     memset(head,-1,sizeof(head)); 67     memset(dfn,0,sizeof(dfn)); 68     memset(low,0,sizeof(low)); 69     memset(belong,0,sizeof(belong)); 70     stop=0; indx=0; tot=0; pat=0; 71     memset(stack,false,sizeof(stack)); 72      73      74     for(int i=0;i<hn;i++){ 75         u=hate[i].u; 76         v=hate[i].v; 77         addedge(u*2,v*2+1); 78         addedge(v*2,u*2+1); 79         addedge(2*u+1,2*v); 80         addedge(2*v+1,2*u); 81     } 82     for(int i=0;i<ln;i++){ 83         u=like[i].u; 84         v=like[i].v; 85         addedge(u*2,v*2); 86         addedge(v*2,u*2); 87         addedge(2*u+1,2*v+1); 88         addedge(2*v+1,2*u+1); 89     } 90     for(int i=0;i<n;i++){ 91         for(int j=i+1;j<n;j++){ 92             if(dis1[i]+dis1[j]>leng){ 93                 addedge(i*2,j*2+1); 94                 addedge(j*2,i*2+1); 95             } 96             if(dis2[i]+dis2[j]>leng){ 97                 addedge(i*2+1,j*2); 98                 addedge(j*2+1,i*2); 99             }100             if(dis1[i]+s1_s2+dis2[j]>leng){101                 addedge(i*2,j*2);102                 addedge(j*2+1,i*2+1);103             }104             if(dis2[i]+s1_s2+dis1[j]>leng){105                 addedge(j*2,i*2);106                 addedge(i*2+1,j*2+1);107             }108         }109     }110     for(int i=0;i<2*n;i++){111         if(dfn[i]==0)112         tarjan(i);113     }114     bool flag=true;115     for(int i=0;i<n;i++){116         if(belong[2*i]==belong[2*i+1]){117             flag=false;118             break;119         }120     }121     return flag;122 }123 124 int main(){125     int u,v; int tmp;126     while(scanf("%d%d%d",&n,&hn,&ln)!=EOF){127         scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);128         for(int i=0;i<n;i++){129         scanf("%d%d",&point[i].x,&point[i].y);130         }131         for(int i=0;i<hn;i++){132             scanf("%d%d",&u,&v);133             u--; v--;134             hate[i].u=u; hate[i].v=v;135         }136         for(int i=0;i<ln;i++){137             scanf("%d%d",&u,&v);138             u--; v--; 139             like[i].u=u; like[i].v=v;140         }141         for(int i=0;i<n;i++){142             tmp=abs(point[i].x-s1.x)+abs(point[i].y-s1.y);143             dis1[i]=tmp;144             tmp=abs(point[i].x-s2.x)+abs(point[i].y-s2.y);145             dis2[i]=tmp;146         }147         s1_s2=abs(s1.x-s2.x)+abs(s1.y-s2.y);148         int lown=1,high=inf,ans=-1;149         while(lown<=high){150             int mid=(lown+high)/2;151             leng=mid;152             if(slove()){153                 ans=mid;154                 high=mid-1;155             }156             else lown=mid+1;157         }158         printf("%d\n",ans);159     }160     return 0;161 }
View Code