您的位置:首页 > 产品设计 > UI/UE

POJ 2749 Building Roads

2011-02-08 01:33 183 查看
由于某个养牛场只能连S1或S2,想到2-SAT,又由于是求最小的最大值,可以二分答案

二分构图时,先把相互讨厌和相互喜欢的加边,然后对每组i和j,X表示到S1的距离,Y表示到S2的距离,i表示与S1相连,~i表示与S2相连,dd表示S1与S2直接的距离

如果Xi+Xj>mid,说明i和j不能同时与S1相连,添加边(i,~j),(j,~i)

如果Yi+Yj>mid,说明i和j不能同时与S2相连,添加边(~i,j),(~j,i)

如果Xi+Yj+dd>mid,说明 i&&~j=0,即不能把i与S1相连的同时,把j与S2相连,则添加边(i,j),(~j,~i)

如果Xj+Yi+dd>mid,说明 ~i&&j=0,即不能把i与S2相连的同时,把j与S1相连,则添加边(~i,~j),(j,i)

用2-SAT解问题时,要找确定的矛盾关系,这也是为什么二分构图时是判断>mid而不是判断<=mid

另外这道题一开始我的思维狭窄了,对于给定的mid值怎样构图时,我在想i和j究竟是同时连S1,或者同时连S2,或者一个连S1,一个连S2,这几种距离到底哪个最大,这样子想太麻烦,回顾上面的做法,我们根据mid值,将四种距离一一进行判断,如果出现矛盾,则添边。2-SAT的解不一定是唯一的,这也与上面每对点最多可能4中连法相符合,我们只要根据可以得到的条件构图,在算法判断是否存在可行解的时候会帮我们挑选一种连法的,并不需要我们在一开始就去指定

代码:

#include<iostream>
#include<stack>
using namespace std;
const int MAX=1005;
struct node
{
int v,next;
}g[MAX*MAX];
int dfn[MAX],low[MAX],inStack[MAX],adj[MAX],bel[MAX];
int a[MAX][MAX],b[MAX][MAX],dis1[MAX],dis2[MAX],x[MAX],y[MAX];
int e,ee,n,A,B,index,cnt,sx1,sx2,sy1,sy2,dd;
stack<int>s;
void add(int u,int v)
{
g[e].v=v; g[e].next=adj[u]; adj[u]=e++;
}
void tarjan(int u)
{
int i,v;
dfn[u]=low[u]=++index;
s.push(u);
inStack[u]=1;
for(i=adj[u];i!=-1;i=g[i].next)
{
v=g[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(inStack[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
cnt++;
do
{
v=s.top();
s.pop();
inStack[v]=0;
bel[v]=cnt;
}while(u!=v);
}
}
bool ok(int mid)
{
int i,j;
memset(adj,-1,sizeof(adj));
memset(dfn,0,sizeof(dfn));
e=index=cnt=0;
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[i][j])
{
add(i,j+n);
add(j,i+n);
add(i+n,j);
add(j+n,i);
}
}
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(b[i][j])
{
add(i,j);
add(j,i);
add(i+n,j+n);
add(j+n,i+n);
}
}
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(dis1[i]+dis1[j]>mid)
{
add(i,j+n);
add(j,i+n);
}
if(dis2[i]+dis2[j]>mid)
{
add(i+n,j);
add(j+n,i);
}
if(dis1[i]+dis2[j]+dd>mid)
{
add(i,j);
add(j+n,i+n);
}
if(dis1[j]+dis2[i]+dd>mid)
{
add(j,i);
add(i+n,j+n);
}
}
}
for(i=1;i<=2*n;i++)
{
if(!dfn[i])
tarjan(i);
}
for(i=1;i<=n;i++)
{
if(bel[i]==bel[i+n])
return false;
}
return true;
}
int main()
{
int i,j,k;
scanf("%d%d%d",&n,&A,&B);
scanf("%d%d%d%d",&sx1,&sy1,&sx2,&sy2);
dd=abs(sx1-sx2)+abs(sy1-sy2);
for(i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&y[i]);
dis1[i]=abs(x[i]-sx1)+abs(y[i]-sy1);
dis2[i]=abs(x[i]-sx2)+abs(y[i]-sy2);
}
for(k=1;k<=A;k++)
{
scanf("%d%d",&i,&j);
a[i][j]=a[j][i]=1;
}
for(k=1;k<=B;k++)
{
scanf("%d%d",&i,&j);
b[i][j]=b[j][i]=1;
}
int l=1,r=9999999,mid,ans=-1;
while(l<=r)
{
mid=(l+r)/2;
if(ok(mid))
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: