AtCoder Beginner Contest 259
作者:互联网
AtCoder Beginner Contest 259
https://atcoder.jp/contests/abc259
先把D放这里,其他的明天补上来
D - Circumferences
题源:abc259_d
人生中第一次做出D题于是就来发题解了
题目描述
给定n个圆(圆心坐标和半径r),以及起点和终点的坐标(这两点必在某个圆上)。
已知 点可以沿着圆的边界(即在圆上移动),试判断能否从起点走到终点。
样例
Sample Input 1
4
0 -2 3 3
0 0 2
2 0 2
2 3 1
-3 3 3
Sample Output 1
Yes
Sample Input 2
3
0 1 0 3
0 0 1
0 0 2
0 0 3
Sample Output 2
No
分析
点一定是在圆上动的,所以当走到两圆交界处的时候就可以顺势走到另一个圆上。
(这里没法放图片,所以可以去原题看样例的截图来辅助来理解)
那么此时就等价于,在这两个圆之间建立一条无向边,于是问题就转化为:求 起点所在的圆 到 终点所在的圆的最短路
分析完毕,梳理一下要做的事:
- 找到起点和终点所在的圆的编号,记录为st和ed;
- 把所有两两相交的圆找到,然后建边(注意特判同心圆不可达的情况)
- 跑最短路的板子
Code
代码写的很潦草,轻喷
SPFA
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int, int> pii;
const int N = 3005*3005, inf = 1e18;
int h[N], ee[N], ne[N], w[N], idx;
int sx, sy, fx, fy, st = 0, ed = 0, n;
int dis[N];
bool vis[N];
//int a[N][N];
void add (int a, int b, int c) {
ee[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}
struct Node {
int x, y, r;
bool operator<(const Node &t)const {
return x < t.x;
}
}e[N];
void spfa () {
queue<int>q;
for (int i = 1; i <= n; i ++) dis[i] = inf;
dis[st] = 0;
q.push(st);
vis[st] = true;
while (!q.empty()) {
int t = q.front();
q.pop();
vis[t] = false;
for (int i = h[t]; i != -1; i = ne[i]) {
int j = ee[i];
if (dis[j] > dis[t]+ w[i]) {
dis[j] = dis[t] + w[i];
if (!vis[j])
q.push (j), vis[j] = true;
}
}
}
//for (int i = 1; i <= n; i ++) cout << dis[i] << endl;
// cout << dis[ed] << endl;
if (dis[ed] != inf) cout << "Yes\n";
else cout << "No\n";
}
signed main () {
cin >> n;
cin >> sx >> sy >> fx >> fy;
for (int i = 1; i <= n; i ++) {
int x, y, r;
cin >> x >> y >> r;
e[i] = {x, y, r};
}
//sort (e + 1, e + n + 1);
for (int i = 1; i <= n; i ++) {
if (st && ed) break;
int x = e[i].x, y = e[i].y, r = e[i].r;
if ((x-sx)*(x-sx) + (y-sy)*(y-sy) == r*r) st = i;
if ((x-fx)*(x-fx) + (y-fy)*(y-fy) == r*r) ed = i;
}
//cout << "st=" << st << ", ed=" << ed << endl;
//建图
memset (h, -1, sizeof h);
for (int i = 1; i <= n; i ++) {
int x = e[i].x, y = e[i].y, r = e[i].r;
for (int j = i + 1; j <= n; j ++) {
int xx = e[j].x, yy = e[j].y, rr = e[j].r;
//if (x == xx && y == yy && r != rr) continue;
int d1 = (x-xx)*(x-xx) + (y-yy)*(y-yy);
int d2 = (r+rr)*(r+rr);
if (d1 != 0 && d1 <= d2) {
//cout << "i=" << i << ", j=" << j << endl;
add (i, j, 1), add (j, i, 1);
//a[i][j] = a[j][i] = 1;
}
}
}
spfa ();
}
//走边框,看看能否走到
//z找圆的交点
//抽象建图,如果两个圆有交点的话就建立一条边
难得做出图论题...
标签:AtCoder,Beginner,idx,int,Sample,vis,259,圆上,dis 来源: https://www.cnblogs.com/CTing/p/16462299.html