码迷,mamicode.com
首页 > 其他好文 > 详细

[poj] 2749 building roads

时间:2017-11-18 12:57:06      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:limit   判断   while   tchar   2-sat   std   http   clu   i++   

原题

2-SAT+二分答案!
最小的最大值,这肯定是二分答案。而我们要2-SATcheck是否在该情况下有可行解。
对于目前的答案limit,首先把爱和恨连边,然后我们n^2枚举每两个点通过判断距离来实现连边,然后跑2-SAT判断是否有可行解
O(n^2logn)
想起来和听起来都很难写,事实上还好吧…

#include<cstdio>
#include<algorithm>
#include<stack>
#include<cstring>
#define inf 97797977
#define N 510
using namespace std;
int n,m,A,B,lovex[2*N],lovey[2*N],hatex[2*N],hatey[2*N],dis1[N],dis2[N],dis,sx1,sx2,sy1,sy2,x[N],y[N],head[2*N];
int bel[2*N],cnt=1,l,r=inf,dfn[2*N],low[2*N],t,mid,sum;
stack <int> stk;
bool instk[2*N];
struct hhh
{
    int to,next;
}edge[10*N*N];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for (;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ;
    if (j==‘-‘) j=getchar(),fu=-1;
    for (;j>=‘0‘ && j<=‘9‘;j=getchar()) ans*=10,ans+=j-‘0‘;
    return ans*fu;
}

void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

bool build()
{
    for (int i=1;i<=B;i++)
    {
    add(lovex[i],lovey[i]);
    add(lovey[i],lovex[i]);
    add(lovex[i]+n,lovey[i]+n);
    add(lovey[i]+n,lovex[i]+n);
    }
    for (int i=1;i<=A;i++)
    {
    add(hatex[i],hatey[i]+n);
    add(hatex[i]+n,hatey[i]);
    add(hatey[i]+n,hatex[i]);
    add(hatey[i],hatex[i]+n);
    }
    for (int i=1;i<=n;i++)
    for (int j=i+1;j<=n;j++)
    {
        int t=0;
        if (dis1[i]+dis+dis2[j]>mid)
        {
        add(i,j);
        add(j+n,i+n);
        t++;
        }
        if (dis2[i]+dis+dis1[j]>mid)
        {
        add(i+n,j+n);
        add(j,i);
        t++;
        }
        if (dis1[i]+dis1[j]>mid)
        {
        add(i,j+n);
        add(j,i+n);
        t++;
        }
        if (dis2[i]+dis2[j]>mid)
        {
        add(i+n,j);
        add(j+n,i);
        t++;
        }
        if (t==4) return 0;
    }
    return 1;
}

void Tarjan(int u)
{
    dfn[u]=low[u]=++t;
    stk.push(u);
    instk[u]=1;
    for (int i=head[u],v;i;i=edge[i].next)
    {
    v=edge[i].to;
    if (!dfn[v])
    {
        Tarjan(v);
        low[u]=min(low[u],low[v]);
    }
    else if (instk[v]) low[u]=min(low[u],dfn[v]);
    }
    if (low[u]==dfn[u])
    {
    sum++;
    int t;
    do
    {
        t=stk.top();
        bel[t]=sum;
        stk.pop();
        instk[t]=0;
    }while(t!=u);
    }
}

bool check()
{
    for (int i=1;i<=n;i++)
    if (bel[i]==bel[i+n]) return 0;
    return 1;
}

int get1(int i)
{
    return abs(sx1-x[i])+abs(sy1-y[i]);
}

int get2(int i)
{
    return abs(sx2-x[i])+abs(sy2-y[i]);
}

int main()
{
    n=read();
    A=read();
    B=read();
    sx1=read();
    sy1=read();
    sx2=read();
    sy2=read();
    dis=abs(sx1-sx2)+abs(sy1-sy2);
    for (int i=1;i<=n;i++)
    {
    x[i]=read();
    y[i]=read();
    }
    for (int i=1;i<=A;i++)
    {
    hatex[i]=read();
    hatey[i]=read();
    }
    for (int i=1;i<=B;i++)
    {
    lovex[i]=read();
    lovey[i]=read();
    }
    for (int i=1;i<=n;i++)
    {
    dis1[i]=get1(i);
    dis2[i]=get2(i);
    }
    while (l<r)
    {
    mid=(l+r)>>1;
    cnt=1;
    memset(dfn,0,sizeof(dfn));
    memset(bel,0,sizeof(bel));
    memset(head,0,sizeof(head));
    if (build())
    {
        t=1;
        sum=1;
        for (int i=1;i<=2*n;i++)
        if (!dfn[i]) Tarjan(i);
        if (check()) r=mid;
        else l=mid+1;
    }
    else l=mid+1;
    }
    printf("%d",l>=inf?-1:l);
    return 0;
}

[poj] 2749 building roads

标签:limit   判断   while   tchar   2-sat   std   http   clu   i++   

原文地址:http://www.cnblogs.com/mrha/p/7856125.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!