P1522 牛的旅行 Cow Tours·最短路

题解

大致题意:给两个连通图添加一条路,使得最远的两个点之间的最短路的值最小
这里的最小的最短路有可能是原本同一个连通图里的最远最短路,也有可能是添加了新边后形成的最远最短路
由于最远的路径由任意两个点组成起点和终点,所以首选Floyd

大致步骤:
1.先求出同一连通图里各个点之间的最短路 - Floyd,如果起终点不是同一个图里的,dis[i][j]显示为最大值
2.求出对于每个点来说,最远的点离它的最短路距离
3.找到连通图里最远的那条最短路,标记为s1
4.之后给不连通的两点之间添一条路,其最远距离应该为 离i最远的距离+i,j之间的距离+离j最远的距离,当然我们添加的边形成的新的最短路,一定是所有添加可能里的最短的那条,标记为s2
5.判断s1和s2里的最大值


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+10;
char s[N];
double ans=0.0;
int n;

struct node{
    int x,y;
    void input(){
        cin>>x>>y;
    }

    double distance(const node& b)const{
        return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y));
    }
}a[N];
double dis[N][N],far[N];

int main()
{
    cin>>n;
    for (int i = 1; i <= n; i++) a[i].input();
    for (int i = 1; i <= n; i++) {
        cin>>s;
        for (int j = 1; j <= n; j++) {
            if(s[j-1]=='1') //s[]='0'时判断是为真!
                dis[i][j]=a[i].distance(a[j]);
            else if(i!=j)dis[i][j]=INF;//顺便初始化
        }
    }

    //先求出任意两点之间的最短路
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if(dis[i][j]>dis[i][k]+dis[k][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
            }
        }
    }

    //然后找到相对于每个点来说 最远的那个点和它的距离
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if(dis[i][j]!=INF) far[i]=max(dis[i][j],far[i]);
            ans=max(ans,far[i]);//找到最远的那个就是联通图内部的直径
        }
    }

    //连接两个连通图
    double ans2=INF;//不会影响答案 因为题目说了必定有两个连通图
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if(dis[i][j]==INF)
                ans2=min(ans2,far[i]+a[i].distance(a[j])+far[j]);
        }
    }
    ans=max(ans,ans2);//找到两者间最大的那个
    printf("%.6f\n",ans);
    return 0;
}
发布了43 篇原创文章 · 获赞 0 · 访问量 1258

猜你喜欢

转载自blog.csdn.net/Yubing792289314/article/details/104024518