hdu 3832 Earth Hour(斯坦纳树)

来源:互联网 发布:jquery字符串转换数组 编辑:程序博客网 时间:2024/05/17 03:08

题意:校园平面内有一些灯,在(X,Y)的点能照亮半径为R的圆的面积。两个圆有一部分重合或者边相切认为这两个圆相连。问删去一些圆是否圆1 2 3是否能直接或间接的联通。若可以则输出最大能删去的圆的数目,不行则输出-1.

原来这种神奇的东西叫做斯坦纳树。。当然最后是最短路写出来的,分别以1 2 3为源点spfa。然后求得D1【】, D2【】, D3【】。则ans = n-min(d1【】 + d2【】+d3【】)。

可能会有疑问,比如1 2 3 连接的边会有重复。不用考虑重复的部分,因为如果最小的情况存在重复的部分,那么一定会有更小的情况。

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>using namespace std;const int N = 205;const int inf = 1 << 28;int a[N][N];int dis[N];int vis[N];int d1[N], d2[N], d3[N];int n;struct node{int x, y, r;}p[N];int f(node a, node b){if( (abs(a.x-b.x) * abs(a.x-b.x) + abs(a.y-b.y) * abs(a.y-b.y)) <= abs(a.r+b.r) * abs(a.r+b.r) )return 1;return inf;}void init(){for( int i = 1; i <= n; i++ ){for( int j = 1; j <= n; j++ ){a[i][j] = (i == j ? 0: inf);}}}void spfa(int st){memset(vis, 0, sizeof(vis));for( int i = 1; i <= n; i++ )dis[i] = inf;dis[st] = 0;vis[st] = 1;queue<int> q;while( !q.empty() )q.pop();q.push(st);while( !q.empty() ){int now = q.front();q.pop();vis[now] = 0;for( int i = 1; i <= n; i++ ){if( !vis[i] ){if( dis[i] > dis[now] + a[now][i] ){dis[i] = dis[now] + a[now][i];q.push(i);vis[i] = 1;}}}}}int main(){int tot;scanf("%d", &tot);while(tot--){scanf("%d", &n);init();for( int i = 1; i <= n; i++ )scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].r);for( int i = 1; i <= n; i++ ){for( int j = 1; j <= n; j++ ){if( i != j )a[i][j] = f(p[i], p[j]);}}spfa(1);for( int i = 1; i <= n; i++ )d1[i] = dis[i];spfa(2);for( int i = 1; i <= n; i++ )d2[i] = dis[i];spfa(3);for( int i = 1; i <= n; i++ )d3[i] = dis[i];int ans = inf;for( int i = 1; i <= n; i++ )ans = min(ans, d1[i] + d2[i] + d3[i]);if( ans == inf )printf("-1\n");elseprintf("%d\n", n - ans - 1);}return 0;}


0 0
原创粉丝点击