• [poj] 2749 building roads


    原题

    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;
    }
    
    
  • 相关阅读:
    Python设计模式
    Python设计模式
    Python设计模式
    Python设计模式
    Python设计模式
    Python设计模式
    Python设计模式
    Python设计模式
    composer安装以及更新问题,配置中国镜像源。
    PHP使用文件排它锁,应对小型并发
  • 原文地址:https://www.cnblogs.com/mrha/p/7856125.html
Copyright © 2020-2023  润新知