HDU 3832 Earth Hour
题意: 有 n 个电灯泡,知道了每个电灯泡的坐标和覆盖半斤,为最多可以去掉多少电灯泡使得 1,2,3,号电灯泡的灯光任然相连。
分析: 分别以 1,2,3为源点求最短路,找到一个点到这三个点的距离和最小值sum,答案即为 n - sum - 1
#include<stdio.h> #include<queue> #include<string.h> using namespace std; #define INF 0x1f1f1f1f #define clr(x)memset(x,0,sizeof(x)) #define maxn 205 struct node { int to,next; }e[1000000]; int tot; int head[maxn]; void add(int s,int t) { e[tot].to=t; e[tot].next=head[s]; head[s]=tot++; } int d1[maxn]; int d2[maxn]; int d3[maxn]; struct dd { int xu,di; bool operator < (dd t)const { return t.di<di; } }tt,in; void dijkstra(int s,int *d) { priority_queue<dd>dis; int i; in.xu=s; in.di=0; d[s]=0; dis.push(in); while(!dis.empty()) { tt=dis.top(); dis.pop(); for(i=head[tt.xu];i;i=e[i].next) { in.xu=e[i].to; in.di=tt.di+1; if(in.di<d[in.xu]) { d[in.xu]=in.di; dis.push(in); } } } } struct p { int x,y,r; }q[203]; int sec(p a,p 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; } int main() { int t,n,i,j; scanf("%d",&t); while(t--) { scanf("%d",&n); clr(head); tot=1; for(i=1;i<=n;i++) scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].r); for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if(sec(q[i],q[j])) { // printf("%d %d __\n",i,j); add(i,j); add(j,i); } memset(d1,INF,sizeof(d1)); dijkstra(1,d1); memset(d2,INF,sizeof(d2)); dijkstra(2,d2); memset(d3,INF,sizeof(d3)); dijkstra(3,d3); int res=INF; for(i=1;i<=n;i++) if(d1[i]+d2[i]+d3[i]<=res) res=d1[i]+d2[i]+d3[i]; if(res==INF) printf("-1\n"); else printf("%d\n",n-res-1); } return 0; }