洛谷P1522 牛的旅行 Cow Tours 并查集+Floyd求最短路

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/weixin_44491423/article/details/104449186