是则赋值为1,否则为0,然后SPFA三次判断1、2、3是否连通,最后找出一个点到1、2、3三点距离最短就可以了
#include <iostream>
#include <cmath>
using namespace std;
const int size = 300;
const int eps = 10000000;
struct circle
{
int x, y, r;
}a[size];
int dis(circle a, circle b)
{
if (((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y)) <= (a.r+b.r) * (a.r+b.r))return 1;
return 0;
}
bool inque[size];
int que[size];
int mapp[size][size];
int dist[5][size];
void SPFA(int s, int n, int kk)
{
memset(inque, false, sizeof(inque));
for (int i = 0; i <= n; i ++){
dist[kk][i] = eps;
}
int rear, front;
rear = 1, front = 0;
que[front] = s;
dist[kk][s] = 0;
inque[s] = true;
while (front< rear){
int u = que[front ++];
inque[u] = false;
for (int i = 1; i <= n; i ++){
if (dist[kk][i] > dist[kk][u] + mapp[u][i]){
dist[kk][i] = dist[kk][u] + mapp[u][i];
if (!inque[i]){
que[rear ++] = i;
inque[i] = true;
}
}
}
}
}
int main()
{
int t;
scanf("%d", &t);
while (t --){
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i ++){
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].r);
}
for (int i = 1; i <= n; i ++){
for (int j = 1; j<= n; j ++){
mapp[j][i] = mapp[i][j] = dis(a[i], a[j]);
}
}
for (int i = 0; i <= n; i ++){
for (int j = 0; j <= n; j ++){
if (!mapp[i][j] && i!=j){
mapp[i][j] = eps;
}
}
}
int check1 = false;
SPFA(1, n, 1);
if (dist[1][2] == eps || dist[1][3] == eps)check1 = true;
SPFA(2, n, 2);
if (dist[2][1] == eps || dist[2][3] == eps)check1 = true;
SPFA(3, n, 3);
if (dist[3][2] == eps || dist[3][1] == eps)check1 = true;
if (check1){
printf("-1\n");
continue;
}
int minn = INT_MAX;
for (int i = 1; i <= n; i ++){
if (minn > dist[1][i]+dist[2][i]+dist[3][i]){
minn = dist[1][i]+dist[2][i]+dist[3][i];
}
}
printf("%d\n", n-1-minn);
}
return 0;
}