hdu 7058 Ink on paper
题意:
- n个墨水点每秒向外扩展0.5cm,问所有点连起来的最小时间的平方
分析:
-
所有点连起来,即成一个连通图
要求最小时间,即最后1点连上前n-1个点所成连通分量的时间
考虑前n-1个点已经成了一个连通分量,第n个点连上连通分量的距离即为n个点生成最小生成树的最大边
问题便转换成了求最小生成树最大边权, t i m e 2 = ( d 2 / 0.5 ) 2 = d 2 {time}^2=(\frac{d}{2}/0.5)^2=d^2 time2=(2d/0.5)2=d2 ,所以连根号都不用开了
-
该题转换成的图是稠密图,所以要用 p r i m prim prim 算法,然后 i n f inf inf 要开 9 e 18 9e18 9e18
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5005, inf=9e18;
int x[N], y[N], a[N][N], d[N];
bool vis[N];
void prim(int n)
{
for(int i=1;i<=n;i++) vis[i]=0, d[i]=inf;
d[1]=0;
for(int i=1;i<n;i++)
{
int mn=inf, p;
for(int j=1;j<=n;j++)
{
if(!vis[j] && d[j]<mn) { mn=d[j]; p=j; }
}
vis[p]=1;
for(int j=1;j<=n;j++)
{
if(!vis[j]) d[j]=min(d[j], a[p][j]);
}
}
int mx=0;
for(int i=1;i<=n;i++) mx = max(d[i], mx);
printf("%lld\n", mx);
}
signed main()
{
int T;
scanf("%lld",&T);
while(T--)
{
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&x[i],&y[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
a[i][j] = a[j][i] = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
}
prim(n);
}
return 0;
}