POJ2749 Building roads
Building roads
题目大意:
平面上有N个点,另外有两个中转点。点与点之间的距离为曼哈顿距离。
N个点中,有的点对相互憎恨,不能连在同一个中转点;有的点对相互友好,必须连在同一个中转点上。中转点之间也有一定的距离。
这样是否可以实现:所有N个点都连接到其中一个中转点,并通过中转点连成一棵树。
如果不能,输出-1
如果能,输出所有方案中,树的直径最小的。直径长度。
————————————————————————————
二分直径的长度
那么建树就变成了一个2-SAT问题,条件:
1.相互憎恨
2.相互友好
3.距离大于二分值的点对方案不能用
总的来说:二分+拆点+2-SAT
注意那个输出-1,忘了就麻烦了!
————————————————————————————
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 const int maxn=505; 8 int n,a,b; 9 int diss,s1x,s1y,s2x,s2y; 10 int xx[maxn],yy[maxn]; 11 int dis[maxn][2],hat[1010][2],lov[1010][2]; 12 bool bz; 13 struct edge 14 { 15 int u,v,nxt; 16 }e[4000005]; 17 int head[maxn<<1],js; 18 void addage(int u,int v) 19 { 20 e[++js].u=u;e[js].v=v; 21 e[js].nxt=head[u];head[u]=js; 22 } 23 inline int dist(int a,int b,int c,int d) 24 { 25 return max(a-c,c-a)+max(b-d,d-b); 26 } 27 int low[maxn<<1],dfn[maxn<<1],cnt,st[maxn<<1],top,lts,lt[maxn<<1]; 28 void tarjan(int u) 29 { 30 low[u]=dfn[u]=++cnt; 31 st[++top]=u; 32 for(int i=head[u];i;i=e[i].nxt) 33 { 34 int v=e[i].v; 35 if(!dfn[v]) 36 { 37 tarjan(v); 38 low[u]=min(low[u],low[v]); 39 } 40 else if(!lt[v]) low[u]=min(low[u],dfn[v]); 41 } 42 if(low[u]==dfn[u]) 43 { 44 lt[u]=++lts; 45 while(st[top]!=u)lt[st[top--]]=lts; 46 --top; 47 } 48 } 49 bool pd(int xx) 50 { 51 memset(head,0,sizeof head);js=0; 52 memset(dfn,0,sizeof dfn); 53 memset(low,0,sizeof low); 54 cnt=0; 55 top=0; 56 memset(lt,0,sizeof lt); 57 lts=0; 58 for(int i=1;i<=a;++i) 59 { 60 int x=hat[i][0],y=hat[i][1]; 61 addage(x,y+n);addage(y+n,x); 62 addage(x+n,y);addage(y,x+n); 63 } 64 for(int i=1;i<=b;++i) 65 { 66 int x=lov[i][0],y=lov[i][1]; 67 addage(x,y);addage(y,x); 68 addage(x+n,y+n);addage(y+n,x+n); 69 } 70 for(int x=1;x<=n;++x) 71 for(int y=x+1;y<=n;++y) 72 { 73 if(x==y)continue; 74 if(dis[x][0]+dis[y][0]>xx)addage(x,y+n),addage(y,x+n); 75 if(dis[x][1]+dis[y][1]>xx)addage(x+n,y),addage(y+n,x); 76 if(dis[x][0]+dis[y][1]+diss>xx)addage(x,y),addage(y+n,x+n); 77 if(dis[x][1]+dis[y][0]+diss>xx)addage(x+n,y+n),addage(y,x); 78 } 79 for(int i=1;i<=(n<<1);++i) 80 if(!dfn[i])tarjan(i); 81 for(int i=1;i<=n;++i) 82 if(lt[i]==lt[i+n])return 0; 83 return 1; 84 } 85 int main() 86 { 87 scanf("%d%d%d",&n,&a,&b); 88 scanf("%d%d%d%d",&s1x,&s1y,&s2x,&s2y); 89 diss=dist(s1x,s1y,s2x,s2y); 90 for(int i=1;i<=n;++i) 91 { 92 scanf("%d%d",xx+i,yy+i); 93 dis[i][0]=dist(s1x,s1y,xx[i],yy[i]); 94 dis[i][1]=dist(s2x,s2y,xx[i],yy[i]); 95 } 96 for(int i=1;i<=a;++i)scanf("%d%d",&hat[i][0],&hat[i][1]); 97 for(int i=1;i<=b;++i)scanf("%d%d",&lov[i][0],&lov[i][1]); 98 int l=0,r=4000001,ans=4000001; 99 while(l<=r) 100 { 101 int mid=(l+r)>>1; 102 if(pd(mid))ans=mid,r=mid-1; 103 else l=mid+1; 104 } 105 cout<<(ans<4000001?ans:-1); 106 return 0; 107 }