题目链接:
http://bailian.openjudge.cn/tm2019/F/
2236 -- Wireless Network
题面描述:
思路:
这题开了10s,所以可以暴力点,每次修复一个点,就将该点相连的那些边建出来,总的时间复杂度为: O(nm)。关键在于如何判定两个点是否是连通的。
刚开始我直接暴力DFS,发现T了,可能是用了DFS之后导致整个题的常数有点大。
另外一种高效地判别连通性的做法是并查集,我们可以在每次添加点的时候还是O(n)的建边,但是在查询连通性的时候就直接O(1)的并查集查询了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define ll long long
using namespace std;
const int N=1010;
struct node{int x;int y;
};
node a[N];
int n,d;
vector<int> edge[N];
int valid[N];
int vis[N];
char op[10];
int fa[N];
void init(){memset(valid,0,sizeof(valid));for(int i=1;i<=n;i++) {edge[i].clear();fa[i]=i;}
}int finds(int x){if(x==fa[x]) return x;return fa[x]=finds(fa[x]);
}void unions(int x,int y){int u=finds(x);int v=finds(y);if(u==v) return ;fa[u]=v;return ;
}int check(int aa,int bb){ll res=1ll*d*d;ll tmp=1ll*(a[aa].x-a[bb].x)*(a[aa].x-a[bb].x)+1ll*(a[aa].y-a[bb].y)*(a[aa].y-a[bb].y);if(tmp<=res) return 1;return 0;
}void build(int x){valid[x]=1;for(int i=1;i<=n;i++){if(!valid[i]) continue;if(check(x,i)){unions(i,x);}}return ;
}int cha(int x,int y){int u=finds(x);int v=finds(y);if(u==v) return 1;return 0;}int main(void){scanf("%d%d",&n,&d);init();for(int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].y);}while(scanf("%s",op)!=-1){if(op[0]=='O'){int x;scanf("%d",&x);build(x);}else{int x,y;scanf("%d%d",&x,&y);int flag=cha(x,y);if(flag) printf("SUCCESS\n");else printf("FAIL\n");}}return 0;
}