• poj2749


    题解:

    二分答案

    先按照原有的条件建边,然后按照二分不能满足的条件建边

    然后判断是否可行

    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    const int N=2005;
    using namespace std;
    int n,m1,m2,num,flag,ans,tot,head[N],X[N],Y[N],dist1[N],dist2[N];
    int scc[N],vis[N],stack1[N],x1,x2,x,y,y11,y2,stack2[N];
    struct edge{int v,next;}g[N*N];
    void init()  
    {  
        memset(head,0,sizeof(head));  
        memset(vis,0,sizeof(vis));  
        memset(scc,0,sizeof(scc));  
        stack1[0]=stack2[0]=num=0;  
        flag=1;  
    }  
    void jb(int u,int v)  
    {  
        num++;  
        g[num].v=v;  
        g[num].next=head[u];  
        head[u]=num;  
    }  
    int js(int x1,int y1,int x2,int y2){return abs(x1-x2)+abs(y1-y2);}  
    void dfs(int cur,int &sig,int &cnt)  
    {  
        if (!flag)return;  
        vis[cur]=++sig;  
        stack1[++stack1[0]]=cur;  
        stack2[++stack2[0]]=cur;  
        for (int i=head[cur];i;i=g[i].next)  
         if (!vis[g[i].v]) dfs(g[i].v,sig,cnt);  
         else if (!scc[g[i].v])  
          while (vis[stack2[stack2[0]]]>vis[g[i].v])stack2[0]--;  
        if (stack2[stack2[0]]==cur)  
         {  
            stack2[0]--;  
            ++cnt;  
            do  
             {  
                scc[stack1[stack1[0]]]=cnt;  
                int tmp=stack1[stack1[0]];  
                if ((tmp>=n&&scc[tmp-n]==cnt)||(tmp<n&&scc[tmp+n]==cnt))  
                 {  
                    flag=0;  
                    return;  
                 }  
             }  
            while (stack1[stack1[0]--]!=cur);  
         }  
    }  
    void solve()  
    {  
        int l=0,r=4000000;  
        ans=-1;  
        while (l<=r)  
         {  
            int mid=(l+r)/2;  
            init();  
            num=0;  
            for (int i=1;i<=m1;i++)  
             {  
                int u=X[i],v=Y[i];  
                jb(u,v+n);jb(u+n,v);  
                jb(v,u+n);jb(v+n,u);  
             }  
            for (int i=m1+1;i<=m1+m2;i++)  
             {  
                int u=X[i],v=Y[i];  
                jb(u,v);jb(v,u);  
                jb(u+n,v+n);jb(v+n,u+n);  
             }  
            for (int i=0;i<n;i++)  
             for (int j=0;j<n;j++)  
              {  
                if (i==j)continue;  
                if (dist1[i]+dist1[j]>mid)jb(i,j+n);  
                if (dist2[i]+dist2[j]>mid)jb(i+n,j);  
                if (dist1[i]+dist2[j]+tot>mid)jb(i,j);  
                if (dist2[i]+dist1[j]+tot>mid)jb(i+n,j+n);  
              }  
            int sig=0,cnt=0;  
            for (int i=0;i<n+n&&flag;i++)  
              if (!vis[i])dfs(i,sig,cnt);   
            if (flag)  
             {  
                ans=mid;  
                r=mid-1;  
             }  
            else l=mid+1;  
         }  
    }  
    int main()  
    {  
        while (~scanf("%d%d%d",&n,&m1,&m2))  
         {  
            scanf("%d%d%d%d",&x1,&y11,&x2,&y2);  
            tot=js(x1,y11,x2,y2);  
            for (int i=0;i<n;i++)  
             {  
                scanf("%d%d",&x,&y);  
                dist1[i]=js(x,y,x1,y11);  
                dist2[i]=js(x,y,x2,y2);  
             }  
            for (int i=1;i<=m1+m2;i++)  
             {  
                scanf("%d%d",&X[i],&Y[i]);  
                X[i]--;Y[i]--;  
             }  
            solve();  
            printf("%d
    ",ans);  
         }  
        return 0;  
    }  
  • 相关阅读:
    XmlDocument和XDocument转String
    C# 6.0 (C# vNext) 新功能之:Null-Conditional Operator(转)
    <%%>与<scriptrunat=server>,<%=%>与<%#%>的区别(转)
    WINDOWS的用户和用户组说明
    C#获取网页内容的三种方式(转)
    C#操作XML方法:新增、修改和删除节点与属性
    linq to xml操作XML(转)
    C#使用tesseract3.02识别验证码模拟登录(转)
    C#修饰符
    SQL语句备份和还原数据库(转)
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8119609.html
Copyright © 2020-2023  润新知