思路:建图(只要联通,边长即为1)对0、1、2三个顶点用3次DIJKSTRA即可解决。
代码:
#include <stdio.h> #include <string.h> #include <math.h> #define MAXN 210 #define inf 1000000000 int head[MAXN], pnt[MAXN*MAXN], next[MAXN*MAXN]; int tot; int used[3][MAXN]; double dist[3][MAXN]; struct Tpoint { double x; double y; double r; }point[MAXN]; int ncase; int n; void addedge (int a, int b) { pnt[tot]=b; next[tot]=head[a]; head[a]=tot++; } double len(struct Tpoint a, struct Tpoint b) { return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } int match(int i, int j) { if (len(point[i],point[j]) <= point[i].r+point[j].r) return 1; else return 0; } int dijkstra (int a) { for (int i=0; i<n; i++) { used[a][i]=0; dist[a][i]=inf; } dist[a][a]=0; for (int i=0; i<n; i++) { int min=inf,minp; for (int j=0; j<n; j++) { if(!used[a][j] && dist[a][j]<min) { min=dist[a][j]; minp=j; } } if(min==inf) return 0; used[a][minp]=1; int idx=head[minp]; while (~idx) { if(!used[a][pnt[idx]] && dist[a][minp] + 1.0 < dist[a][pnt[idx]]) //length[idx]=1 dist[a][pnt[idx]]=dist[a][minp] + 1.0; idx=next[idx]; } } return 1; } int main() { scanf("%d",&ncase); while (ncase--) { tot=0; memset (head,-1,sizeof(head)); memset (next,-1,sizeof(next)); scanf ("%d",&n); for (int i=0; i<n; i++) { scanf ("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].r); for (int j=0; j<i;j++) { if (match(i,j)) { //printf("%d %d %lf\n",i,j,len(point[i],point[j])); addedge(i,j); addedge(j,i); } } } for (int i=0; i<3; i++) dijkstra(i); //for(int i=0; i<n; i++) // printf("%d:%.3lf\n",i,dist[0][i]); int min=inf,minp; for(int i=0; i<n; i++) { if (dist[0][i]+dist[1][i]+dist[2][i] < min) { min=dist[0][i]+dist[1][i]+dist[2][i]; minp=i; } } if(min==inf) printf("-1\n"); else printf("%d\n",n-(min+1)); } }