欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

P1522 牛的旅行 Cow Tours·最短路

程序员文章站 2022-03-21 07:50:36
...

题解

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

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


P1522 牛的旅行 Cow Tours·最短路
P1522 牛的旅行 Cow Tours·最短路
P1522 牛的旅行 Cow Tours·最短路


#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;
}
相关标签: 洛谷