(1)思路:
斯坦纳树的结论:以1,2,3为起点,跑三个最短路,每次得到一个最短距离,
然后求ans = MIN(ans,d[1]+d[2]+d[3])得到最小值,就是最小需要选取的点的个数。
n-ans就是结果。
(2)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 220;
const int INF = 1e9+10;
struct Node{
double x,y,r;
}cur[maxn];
int dis[4][maxn],mp[maxn][maxn],vis[maxn],n,m;
void spfa(int st){
for(int i=1;i<=n;i++){
vis[i] = 0;dis[st][i] = INF;
}
dis[st][st] = 0;
queue <int> q;
q.push(st);
while(!q.empty()){
int x = q.front();q.pop();vis[x] = 0;
for(int i=1;i<=n;i++)
if(mp[x][i]!=INF&&dis[st][i]>dis[st][x]+mp[x][i]){
dis[st][i] = dis[st][x]+mp[x][i];
if(vis[i]==0){
vis[i] = 1;
q.push(i);
}
}
}
}
int main(void)
{
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&cur[i].x,&cur[i].y,&cur[i].r);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
if(i!=j){
double tp = sqrt((cur[i].x-cur[j].x)*(cur[i].x-cur[j].x)+(cur[i].y-cur[j].y)*(cur[i].y-cur[j].y));
double r = cur[i].r+cur[j].r;
if(tp<=r) mp[i][j] = 1;
else mp[i][j] = INF;
}
else mp[i][j] = 0;
}
spfa(1);
spfa(2);
spfa(3);
int ans = INF;
for(int i=1;i<=n;i++){
if(dis[1][i]==INF||dis[2][i]==INF||dis[3][i]==INF) continue;
ans = min(ans,dis[1][i]+dis[2][i]+dis[3][i]+1);
}
printf("%d\n",ans==INF?-1:(n-ans));
}
return 0;
}