[ICPC2014 WF]Sensor Network


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

代码:

#include 
#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(he0&&!bb[v[i]])
            {
                bb[v[i]]=true;
                jl[v[i]]=jl[u]+1;
                dl[ta++]=v[i];
            }
        }
        he+=1;
    }
    return jl[T]0&&jl[v[i]]==jl[u]+1)
        {
            int t=dfs(v[i],zjg)
            {
                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\n",jg);
    if(jg==1)ans[0]=1;
    for(int i=0;i

此外,模拟退火也能过。