本篇博客是我搬运自己洛谷上投的这题的题解,只不过没有被官方发布。
其实我已经有三篇题解是已经被展示啦(得意)
今天夜晚刚颓废完,想给自己的C++系列填个坑。这道题虽然是蓝题,但我感觉可以划到橙题蒟蒻言论
下面就是完全ctrl cv自己的博客内容啦!
从拿到这道题到AC它,花了三小时。。。太蒻了
蒟蒻自闭了
蒟蒻也是开始学的floyd算法,题解各位犇犇已经给出了大致过程,所以蒟蒻想向
还没学floyd的犇犇们普及一下这种算法,我们先由floyd是个什么东西说起~
Floyed-Warshall算法 O(N^3)
简称Floyed(弗洛伊德)算法,是最简单的最短路径算法,可以计算图中任意两点
间的最短路径。Floyed的时间复杂度是O (N3),适用于出现负边权的情况。
以下没有特别说明的话,dis[u][v]表示从u到v最短路径长度,w[u][v]表示连
接u,v的边的长度。
算法描述:
初始化:点u、v如果有边相连,则dis[u][v]=w[u][v]。如果不相连则
dis[u]
[v]=0x7fffffff
For (k = 1; k <= n; k++)
For (i = 1; i <= n; i++)
For (j = 1; j <= n; j++)
If (dis[i][j] >dis[i][k] + dis[k][j])
dis[i][j] = dis[i][k] + dis[k][j];
算法结束:dis[i][j]得出的就是从i到j的最短路径。
算法分析&思想讲解:
三层循环,第一层循环中间点k,第二第三层循环起点终点i、j,算法的思想
很容易理解:如果点i到点k的距离加上点k到点j的距离小于原先点i到点j的距
离,那么就用这个更短的路径长度来更新原先点i到点j的距离。
在上图中,因为dis[1][3]+dis[3][2]<dis[1][2],所以就用dis[1]
[3]+dis[3][2]来更新原先1到2的距离。
我们在初始化时,把不相连的点之间的距离设为一个很大的数,不妨可以
看作这两点相隔很远很远,如果两者之间有最短路径的话,就会更新成最短路
径的长度。Floyed算法的时间复杂度是O(N3)。
Floyed算法变形:
如果是一个没有边权的图,把相连的两点间的距离设为dis[i][j]=true,不
相连的两点设为dis[i][j]=false,用Floyed算法的变形:
For (k = 1; k <= n; k++)
For (i = 1; i <= n; i++)
For (j = 1; j <= n; j++)
dis[i][j] = dis[i][j] || (dis[i][k] && dis[k][j]);
最后再强调一点:用来循环中间点的变量k必须放在最外面一层循环。
那么我们回到这题!
【算法分析】 用Floyed求出任两点间的最短路,然后求出每个点到所有可达的点的最大距离,记做mdis[i]。(Floyed算法)
r1=max(mdis[i])
然后枚举不连通的两点i,j,把他们连通,则新的直径是
mdis[i]+mdis[j]+(i,j)间的距离。
r2=min(mdis[i]+mdis[j]+dis[i,j])
re=max(r1,r2)
re就是所求。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
double f[151][151],m[151],minx,r,temp,x[151],y[151],maxint=1e12;
double dist(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])) ;
}
int main()
{ int i,j,n,k;char c;
cin>>n;
for(i=1;i<=n;i++)cin>>x[i]>>y[i];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{ cin>>c;
if(c=='1')f[i][j]=dist(i,j);
else f[i][j]=maxint;
}
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j&&i!=k&&j!=k)
if(f[i][k]<maxint-1&&f[k][j]<maxint-1)
if(f[i][j]>f[i][k]+f[k][j])
f[i][j]=f[i][k]+f[k][j];
memset(m,0,sizeof(m));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(f[i][j]<maxint-1&&m[i]<f[i][j])m[i]=f[i][j];
minx=1e20;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j&&f[i][j]>maxint-1)
{temp=dist(i,j);
if(minx>m[i]+m[j]+temp)minx=m[i]+m[j]+temp;
}
r=0;
for(i=1;i<=n;i++)if (m[i]>minx)minx=m[i];
printf("%.6lf",minx);
return 0;
}
这就是蒟蒻的题解了,如果对大家有用的话还请多多支持!
–2020.03.19 补全我的C++记忆。。。