题目链接:https://www.luogu.com.cn/problem/P1522
1.用并查集找位于同一牧场的牧区,找的过程中初始化各点的距离。
2.用Floyd算法更新位于同一牧场的各牧区的最短距离。
3.枚举任意在相同牧场的牧区,更新以这一牧区为起始点能到同一牧场其它牧区的最大距离。
4.枚举任意位于不同牧场的牧区,更新连接两个牧场后新牧场的最小直径。
5.枚举所有牧场直径,更新答案。
下贴代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=160;
const int inf=0xfffffff;
struct node
{
int x,y;
}p[maxn];
int n;
int fa[maxn];
char str[maxn];
double vertex[maxn][maxn];
double r[maxn];
double ans;
double dist(node a,node b)//求距离
{
return sqrt((a.y-b.y)*(a.y-b.y)*1.0+(a.x-b.x)*(a.x-b.x)*1.0);
}
int find(int x)//并查集
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
void floyd()//求最短路
{
for(int k=1;k<=n;k++)
for(int j=1;j<=n;j++)
for(int i=1;i<=n;i++)
{
if(find(i)==find(j)&&find(k)==find(j))
{
//puts("1");
if(vertex[i][k]!=inf&&vertex[k][j]!=inf)
if(vertex[i][j]>(vertex[i][k]+vertex[k][j]))
vertex[i][j]=vertex[i][k]+vertex[k][j];
}
}
}
int main()
{
scanf("%d",&n);
ans=inf;
for(int i=1;i<=n;i++)
scanf("%d %d",&p[i].x,&p[i].y);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
vertex[i][j]=inf;
for(int i=1;i<=n;i++)
vertex[i][i]=0;
for(int i=1;i<=n;i++)
{
scanf("%s",str+1);
for(int j=1;j<=n;j++)
{
if(str[j]=='1')
{
int x=find(i),y=find(j);
if(x!=y)
fa[x]=y;
double dis=dist(p[i],p[j]);
vertex[i][j]=vertex[j][i]=dis;
}
}
}
floyd();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
//cout<<vertex[i][j]<<endl;
if(find(i)==find(j)&&vertex[i][j]!=inf&&r[i]<vertex[i][j])
r[i]=vertex[i][j];//找直径
}
//for(int i=1;i<=n;i++)
//cout<<r[i]<<endl;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(find(i)!=find(j)&&(r[i]+r[j]+dist(p[i],p[j]))<ans)
ans=r[i]+r[j]+dist(p[i],p[j]);
for(int i=1;i<=n;i++)
if(r[i]>ans)
ans=r[i];
printf("%.6lf\n",ans);
return 0;
}