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 }
View Code

 

posted on 2019-06-01 09:24  gryzy  阅读(121)  评论(0编辑  收藏  举报

导航