• [ICPC2014 WF]Sensor Network


    题意:有一些点,距离不超过(d)的连边。求最大团。
    题解:
    首先,最大团是NPC的。
    求最大团,可以把边取反,变为最大独立集。
    如果这个图是二分图,那我们就可以做了。
    这个图是二分图,说明可以把能选择点分为两部分,每部分的最远点对距离都不超过(d)
    考虑缩小可行集合使其满足二分图性质。
    枚举答案的最远点对,那么,以这两个为圆心。距离为半径作圆,两个圆个公共部分是可行区域。
    这个区域是“圆规”的形状,即“()”。
    不难发现,在中间水平切一刀,上线两部分的最远点对都不超过(d)
    这样就变成二分图了。
    时间复杂度:(O(n^2*m*sqrt{n})),即(O(n^{4.5}))
    能过。

    代码:

    #include <stdio.h>
    #define MN 210
    #define MM 2010
    #define inf 99999999
    int X[102],Y[102];
    bool ck(int x,int y,int d)
    {
        return x*x+y*y<=d;
    }
    bool inc(int i,int j,int d)
    {
        return ck(X[i]-X[j],Y[i]-Y[j],d);
    }
    bool bk[102][102];int dd[102],co[102];
    void dfs0(int u,int c,int n)
    {
        if(co[u])return;
        co[u]=c;
        for(int i=1;i<=n;i++)
        {
            if(bk[u][i])
                dfs0(i,3-c,n);
        }
    }
    int fr[MN],ne[MM],v[MM],w[MM],bs=0;bool bb[MN];
    int dy[MN],dl[MN],od[MM],S,T,N,jl[MN];
    void add(int a,int b,int c)
    {
    	v[bs]=b;
    	w[bs]=od[bs]=c;
    	ne[bs]=fr[a];
    	fr[a]=bs++;
    }
    void addb(int a,int b,int c)
    {
        add(a,b,c);
        add(b,a,0);
    }
    bool bfs()
    {
        for(int i=1;i<=N;i++)
        {
    		jl[i]=inf;
    		bb[i]=false;
        }
        int he=0,ta=1;
        dl[0]=S;jl[S]=0;bb[S]=true;
        while(he<ta)
        {
            int u=dl[he];
            for(int i=fr[u];i!=-1;i=ne[i])
            {
                if(w[i]>0&&!bb[v[i]])
                {
                    bb[v[i]]=true;
                    jl[v[i]]=jl[u]+1;
                    dl[ta++]=v[i];
                }
            }
            he+=1;
        }
        return jl[T]<inf;
    }
    int dfs(int u,int z)
    {
        if(u==T)
            return z;
        for(int &i=dy[u];i!=-1;i=ne[i])
        {
            if(w[i]>0&&jl[v[i]]==jl[u]+1)
            {
                int t=dfs(v[i],z<w[i]?z:w[i]);
                if(t!=-1)
                {
                    w[i]-=t;w[i^1]+=t;
                    return t;
                }
            }
        }
        return -1;
    }
    int dinic()
    {
        int jg=0;
        while(bfs())
        {
            for(int i=1;i<=N;i++)
    			dy[i]=fr[i];
            while(1)
            {
                int rt=dfs(S,inf);
                if(rt==-1)
                    break;
                jg+=rt;
            }
        }
        return jg;
    }
    int ans[102];
    int main()
    {
        int n,d,jg=1;
        scanf("%d%d",&n,&d);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&X[i],&Y[i]);
        for(int a=1;a<=n;a++)
        {
            for(int b=1;b<=n;b++)
            {
                if(a==b)continue;
                if(!inc(a,b,d*d))
                    continue;
                int m=0,r=(X[a]-X[b])*(X[a]-X[b])+(Y[a]-Y[b])*(Y[a]-Y[b]);
                for(int i=1;i<=n;i++)
                {
                    if(i==a||i==b)continue;
                    if(inc(i,a,r)&&inc(i,b,r))
                        dd[++m]=i;
                }
                for(int i=1;i<=m;i++)co[i]=0;
                for(int i=1;i<=m;i++)
                {
                    for(int j=1;j<=m;j++)
                        bk[i][j]=!inc(dd[i],dd[j],r);
                }
                for(int i=1;i<=m;i++)
                {
                    if(co[i]==0)
                        dfs0(i,1,m);
                }
                N=m+2;S=N-1;T=N;bs=0;
                for(int i=1;i<=N;i++)fr[i]=-1;
                for(int i=1;i<=m;i++)
                {
                    if(co[i]==1)
                    {
                        addb(S,i,1);
                        for(int j=1;j<=m;j++)
                        {
                            if(bk[i][j])
                                addb(i,j,inf);
                        }
                    }
                    else addb(i,T,1);
                }
                int rt=m-dinic()+2;
                if(rt>jg)
                {
                    int s=0;
                    for(int i=1;i<=m;i++)
                    {
                        if(co[i]==1&&jl[i]!=inf)
                            ans[s++]=dd[i];
                        else if(co[i]==2&&jl[i]==inf)
                            ans[s++]=dd[i];
                    }
                    ans[s++]=a;ans[s++]=b;
                    jg=rt;
                }
            }
        }
        printf("%d
    ",jg);
        if(jg==1)ans[0]=1;
        for(int i=0;i<jg;i++)
            printf("%d ",ans[i]);
        return 0;
    }
    

    此外,模拟退火也能过。

  • 相关阅读:
    源码安装jdk
    yum操作的一些笔记
    Tomcat笔记
    源码编译安装zabbix server端和agent端
    用nginx做反向代理时 通过设置让后台真实服务器日志记录客户端的IP
    LVS负载均衡的两种调度模式:NAT和DR
    nginx配置文件详解
    FPGA高级设计——时序分析和收敛(转)
    12个有趣的C语言面试题
    LDO稳压器工作原理
  • 原文地址:https://www.cnblogs.com/lnzwz/p/14305430.html
Copyright © 2020-2023  润新知