题解 P3416 【[USACO16DEC]Moocast(silver)奶牛广播-银】
题意
求从一个点出发最多可以访问到的点数
算法
1、Floyd。
此解法详见其他题解。
2、DFS(我的方法)
不要轻视DFS,在本题中TA的效率为O(n^2),而Floyd的效率仅为O(N^3),碾压。
方法为从一个点出发DFS,搜到点就tot++,比较tot和ans。
存边时我采用的是邻接表,为了在DFS中减少循环。
至于处理能否到达,可以用一个巧妙的方法:
题目意思是如果sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]))<=p[i]成立,则 i 可以到 j,但小数运算十分讨厌,我们可以两边同时平方来处理,转变为sqr(x[i]-x[j])+sqr(y[i]-y[j])<=p[i]*p[i]。
以下为代码:
#include<cstdio>
int n,ans,tot,x[205],y[205],p[205],edge[205][205];
bool v[205];
inline int sqr(int x){return x*x;}
void dfs(int k){
if(v[k])return;
v[k]=1;tot++;
for(register int i=1;i<=edge[k][0];i++)dfs(edge[k][i]);
}
int main(){
scanf("%d",&n);
for(register int i=1;i<=n;i++)scanf("%d%d%d",x+i,y+i,p+i);
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++)
if(sqr(p[i])>=sqr(x[i]-x[j])+sqr(y[i]-y[j]))
edge[i][++edge[i][0]]=j;
for(register int i=1;i<=n;i++){
for(register int j=1;j<=n;j++)v[j]=0;
tot=0;
dfs(i);
if(tot>ans)ans=tot;
}
printf("%d",ans);
}