洛谷 P3958 [NOIP2017 提高组] 奶酪(建图,dfs)
传送门
解题思路
\(n^2\) 遍历每个点,判断两个空洞之间是否能联通,若联通,则在两个点之间建一条边。
然后在能抵达上表面的点和能抵达下表面的点分别建边连向上表面/下表面,最后dfs判断上下表面是否联通即可。
总复杂度 \(O(n^2)\)
AC代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+5;
int t,n;
long long h,x[maxn],y[maxn],z[maxn],r;
int cnt,p[maxn],vis[maxn];
struct node{
int v,next;
}e[maxn*maxn*2];
void insert(int u,int v){
cnt++;
e[cnt].v=v;
e[cnt].next=p[u];
p[u]=cnt;
}
inline long long getdis(int i,int j){
return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
}
bool dfs(int u){
if(u==n+1) return 1;
vis[u]=1;
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(vis[v]) continue;
if(dfs(v)) return 1;
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cnt=0;
memset(vis,0,sizeof(vis));
memset(p,-1,sizeof(p));
cin>>n>>h>>r;
for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(getdis(i,j)<=4*r*r){
insert(i,j);
insert(j,i);
}
}
}
for(int i=1;i<=n;i++){
if(z[i]<=r){
insert(i,n+1);
insert(n+1,i);
}
if(h-z[i]<=r){
insert(0,i);
insert(i,0);
}
}
if(dfs(0)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
//NOIP2017提高组Day2 t1