题意是给定n个点,包括坐标和这个点照亮范围,使1、2、3三点连通最多删去几个点,也就是最少留下几个点
构造两两之间的边,如果同一个点边权是0,如果可以照亮其中一个边权为1
求出1和2和3到所有点最短路,d=min(dist[1][i]+dist[2][i]+dist[3][i]+1),可连通的话n-d-1即为答案
会不会包含重复路?不会,如果有会有更短的路
卧槽===想不到啊。。。我以为是动规TUT
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 struct dian{ 7 int x,y,r; 8 }a[205]; 9 int g[205][205],vis[205],dist[5][205],n; 10 void dijkstra(int k) 11 { 12 memset(dist[k],0x3f,sizeof(dist[k])); 13 memset(vis,0,sizeof(vis)); 14 dist[k][k]=g[k][k]; 15 for (int i=1;i<=n;i++){ 16 int minx=inf,mini=-1; 17 for (int j=1;j<=n;j++) 18 if (dist[k][j]<minx&&vis[j]==0) {minx=dist[k][j]; mini=j;} 19 if (mini==-1) break; 20 vis[mini]=1; 21 for (int j=1;j<=n;j++) 22 dist[k][j]=min(dist[k][j],dist[k][mini]+g[mini][j]); 23 } 24 } 25 int main() 26 { 27 int T,i,j,k,ans; 28 scanf("%d",&T); 29 while (T--){ 30 scanf("%d",&n); 31 for (i=1;i<=n;i++) 32 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].r); 33 memset(g,0x3f,sizeof(g)); 34 for (i=1;i<=n;i++) 35 for (j=1;j<=n;j++){ 36 if (i==j) {g[i][j]=0; continue;} 37 if ((a[i].r+a[j].r)*(a[i].r+a[j].r)>= 38 (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)) 39 g[i][j]=1; 40 } 41 for (i=1;i<=3;i++) dijkstra(i); 42 ans=inf; 43 for (i=1;i<=n;i++) 44 if (dist[1][i]!=inf&&dist[2][i]!=inf&&dist[3][i]!=inf) 45 ans=min(ans,dist[1][i]+dist[2][i]+dist[3][i]); 46 if (ans==inf) printf("-1\n"); 47 else printf("%d\n",n-ans-1); 48 } 49 return 0; 50 }