usaco Cow Tours

多源最短路

弗洛伊德算法+并查集

很适合用来训练图论的思维

/*
ID:zhdxzwj1
LANG:C++
PROG:cowtour
*/
#include <bits/stdc++.h>
double ma[152][152];
char flag[152][152];
char fei;
double  d[152];
double  dd[152]={0};
struct vertex
{
 int x,y;
}v[152];
int bing[152];
int main()
{
    freopen("cowtour.in","r",stdin);
    freopen("cowtour.out","w",stdout);
    int n;
    scanf("%d",&n);
    int i,j,k;
    for(i=0;i<n;i++)
        {
            scanf("%d %d",&v[i].x,&v[i].y);
        }
        memset(bing,-1,152*sizeof(int));
         scanf("%c",&fei);
    //构建原始的图信息,包括两点距离计算,并查集产生
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
       {
        scanf("%c",&flag[i][j]);
        if(flag[i][j]=='1')
        {
         if(bing[i]==-1&&bing[j]==-1)
         {
           bing[j]=i;
           bing[i]=i;
         }
         else
         {
             if(bing[i]==-1)
             {
                 bing[i]=bing[j];
             }
             else if(bing[j]==-1)
             {
                   bing[j]=bing[i];
             }
             else
             {
                 for(k=0;k<n;k++)
                {
                   if(bing[k]==bing[j])
                    bing[k]=bing[i];
                }
             }
         }
         ma[i][j]=sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x)+(v[i].y-v[j].y)*(v[i].y-v[j].y));
        }
        else {
                if(i!=j)
                  ma[i][j]=INT_MAX;
                else
                  ma[i][j]=0;
            }
        }
        scanf("%c",&fei);
    }
    for(i=0;i<n;i++)
        if(bing[i]==-1)
         bing[i]=i;
//Floyd算法最短路
    for(k=0;k<n;k++)
        for(i=0;i<n;i++)
          for(j=0;j<n;j++)
          {
              ma[i][j]=std::min(ma[i][j],ma[i][k]+ma[k][j]);
          }
//连通子图的每个点对应的直径(不一定是最大的)
    for(i=0;i<n;i++)
    {
        d[i]=0;
        for(j=0;j<n;j++)
        {
            if(ma[i][j]!=INT_MAX)
            d[i]=std::max(d[i],ma[i][j]);
        }

    }
     k=5;
    double ans=INT_MAX;
    //每个子图的最大直径
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
        {
            if(bing[i]==bing[j])
            {
                dd[bing[i]]=std::max(dd[bing[i]],ma[i][j]);
            }
        }
        //尝试连接两个牧场,比较新直径和两个原始直径,最大者即为新的直径
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
    {
        if(bing[i]!=bing[j])
        {
            double temp;
            temp=std::max(std::max(d[i]+d[j]+sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x)+(v[i].y-v[j].y)*(v[i].y-v[j].y)),dd[bing[i]]),dd[bing[j]]);
            ans=std::min(temp,ans);
        }
    }
    printf("%.6f\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值