标签:pow name mis 有一个 load 题解 test mic 并查集
题意:有一个矩形,有\(k\)个警报器,警报器所在半径\(r\)内不能走,问是否能从左上角走到右下角.
题解:用并查集将所有相交的圆合并,那么不能走的情况如下图所示
所以最后查询判断一下即可.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#include <unordered_set>
#include <unordered_map>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
struct misaka{
ll x;
ll y;
ll r;
}s[N];
int m,n,k;
int p[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
ll pow(ll x){
return x*x;
}
bool judge(misaka a,misaka b){
return pow(a.x-b.x)+pow(a.y-b.y)<=a.r*a.r+b.r*b.r+2*a.r*b.r;
}
bool check(misaka a,misaka b){
if(a.x>a.r && a.y+a.r<m) return false;
if(b.x+b.r<n && b.y-b.r>0) return false;
return true;
}
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;++i){
scanf("%lld%lld%lld",&s[i].x,&s[i].y,&s[i].r);
p[i]=i;
}
for(int i=1;i<=k;++i){
for(int j=i+1;j<=k;++j){
if(judge(s[i],s[j])){
int x=find(i);
int y=find(j);
if(x!=y){
p[x]=y;
}
}
}
}
for(int i=1;i<=k;++i){
find(i); //压缩路径
}
bool ok=true;
for(int i=1;i<=k;++i){
for(int j=1;j<=k;++j){
if(check(s[i],s[j]) && p[i]==p[j])
ok=false;
}
}
if(ok) puts("S");
else puts("N");
return 0;
}
参考于:https://blog.csdn.net/a1214034447/article/details/102818357
2019-2020 ACM-ICPC Brazil Subregional Programming Contest Problem A Artwork (并查集)
标签:pow name mis 有一个 load 题解 test mic 并查集
原文地址:https://www.cnblogs.com/lr599909928/p/13176488.html