http://acm.hdu.edu.cn/showproblem.php?pid=3832
思路:
计算3次裸Dijstra 求出前三个点到任意点的距离
枚举以每个点为中间点连接前三个点 Min( dist[1][i] + dist[2][i] + dist[3][i]; )
答案为 n - Min - 1
#include<stdio.h>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 210;
const int inf = 1<<29;
int n;
struct Node
{
int x,y,r;
}node[maxn];
int dist[5][maxn];
bool vis[maxn];
int map[maxn][maxn];
typedef pair<int,int>pii;
int getDis( Node a,Node b )
{
return (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
}
void getMap()
{
for( int i = 1; i <= n; i ++ )
{
for( int j = 1; j <= n; j ++ )
{
if( i == j )
continue;
int dis = getDis( node[i],node[j] );
if( dis <= (node[i].r + node[j].r)*(node[i].r + node[j].r) )
{
map[i][j] = map[j][i] = 1;
}
}
}
}
void Dijstra( int x )
{
priority_queue<pii,vector<pii>,greater<pii> >que;
memset( vis,0,sizeof(vis) );
int *dis = dist[x];
for( int i = 1; i <= n; i ++ )
dis[i] = inf;
dis[x] = 0;
que.push( make_pair(dis[x],x) );
while( !que.empty() )
{
pii u = que.top(); que.pop();
int v = u.second;
if( vis[v] )
continue;
vis[v] = true;
for( int i = 1; i <= n; i ++ )
{
if( map[v][i] && dis[i] > dis[v] + 1 )
{
dis[i] = dis[v] + 1;
que.push( make_pair( dis[i],i ) );
}
}
}
}
int main()
{
//freopen("data.txt","r",stdin);
int t;
scanf("%d",&t);
while( t-- )
{
scanf("%d",&n);
for( int i = 1; i <= n; i ++ )
{
scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].r);
}
memset( map,0,sizeof(map) );
getMap();
int Min = inf;
for( int i = 1; i <= 3; i ++ )
{
Dijstra(i);
}
for( int i = 1; i <= n; i ++ )
{
int temp = dist[1][i] + dist[2][i] + dist[3][i];
if( temp < Min )
Min = temp;
}
if( Min == inf )
puts("-1");
else
printf("%d\n",n - Min - 1);
}
return 0;
}