洛谷 P1522 牛的旅行 Cow Tours

题意

这道题意较难理解:john有多个农场,每个农场有多个农区,给出农区的位置以及农区之间是否有路线(就是邻接表),求出用最好的方法连接后(可以理解为合并后的一个农场),求出这个农场直径(相距最远的两个农区的最短路)

做法

我的做法是先将农场给划分开来,因为连接后的的直径有三种可能,先将第一个农场记作x,另一个记作y:

  1. x的直径;
  2. y的直径;
  3. 分别从连接点出发,x的最长路线加上y的最长路线再加上连接点的距离。

代码如下,只要理解了连通块的转换以及最短路的算法进行暴力枚举即可。

#include<bits/stdc++.h>
using namespace std;
int x[155],y[155];
double d[155][155], D[155][155];
int belong[155];
int p[155];
int q[155][155];
int n;
double f[155];
double kuai[155][155];
void DFS(int l,int h)
{
    belong[l]=h;
    q[h][++p[h]]=l;//p[h]记录这个连通块有多少个农区,q数组记录第h个连通块的第p[h]个农区 
    for(int i=1;i<=n;++i)
    {
        if(i==l) continue;
        if(!belong[i] && d[l][i]<1e9) 
            DFS(i,h);
    }
}

double zhijing(int t,int k)
{
    int v[155]={};
    double ws[155];
    for(int i=1;i<=p[t];++i)
        ws[i]=1e9;
    ws[k]=0;
    double ans=0;
    for(int i=1;i<p[t];++i)
    {
        int ok=-1;
        for(int j=1;j<=p[t];++j)
          if(!v[j]&&(ok==-1||ws[j]<ws[ok]))
            ok=j;
        v[ok]=1; 
        for(int j=1;j<=p[t];++j)
            if(d[q[t][ok]][q[t][j]]) 
                ws[j]=min(ws[j],ws[ok]+d[q[t][ok]][q[t][j]]);     
    }
    for(int i=1;i<=p[t];++i)
    {
        if(i==k) continue;
        ans=max(ans,ws[i]);
    }       
    kuai[t][k]=ans;
    return ans;
}//最短路算法 
double liantong(int x,int y,int x1,int y1, double dd)
{
     return max(max(kuai[x][x1]+kuai[y][y1]+dd,f[x]),f[y]);
}
int main() 
{
    //freopen("cowtour.in","r",stdin);
    //freopen("cowtour.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&x[i],&y[i]);
    char t;
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=n;++j)
        {
           scanf(" %c",&t);//数据会有空格 
           int a=x[i]-x[j];
           int b=y[i]-y[j];
           d[i][j]=(t=='1'?sqrt(a*a+b*b):1e9);
           d[j][i]=d[i][j];
        }
    }
    int  k=0;
    for(int i=1;i<=n;++i)
        if(!belong[i]) DFS(i,++k);//DFS求出每个连通块 
    for(int i=1;i<=k;++i)
    {   
        for(int j=1;j<=p[i];++j)
           f[i]=max(f[i],zhijing(i,j));
    }

    double tr=1e9;
    for(int i=1;i<=k;++i)
    {
        for(int j=1;j<=k;++j)
        {
            if(i==j) continue;
            for(int a1=1;a1<=p[i];++a1)
            {
                for(int a2=1;a2<=p[j];++a2)
                {
                    int a = q[i][a1], b = q[j][a2];
                    int dx = x[a]-x[b];
                    int dy = y[a]-y[b];
                    tr=min(tr,liantong(i,j,a1,a2,sqrt(dx*dx+dy*dy)));
                }
            }
        }
    }
    printf("%.6f\n",tr);
    return 0;
}

 

posted @ 2022-02-12 16:04  LikC1606  阅读(58)  评论(0编辑  收藏  举报