[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
此外,模拟退火也能过。