这道题在洛谷上的链接:
真心很无语,怎么会有这么奇怪的题。。。呃呃,题解。大家的做法几乎是一样的,我都不能理解,只有一个人的做法和我想的一样,可是很麻烦。
大家基本都是用Floyd求出每个点所能到达的最远的最短路,设为md[i],枚举不连通的两个结点i和j,求出最小的md[i]+md[j]+dis[i][j](dis[i][j]指两点间距离)。这还不算什么,更坑的是,又求出最大的md[i],将其与min(md[i]+md[j]+dis[i][j])比较,较大的为答案,说是什么将两个牧场连通后,直径如果要经过新路,可能还比原来牧场的直径小,这个很好理解,可是为什么要和所有牧场的直径比较?不应该是求max(dd[i],dd[j],md[i]+md[j]+dis[i][j])吗(dd[i]是指i所在连通块的直径)?然后最小的那个就是答案。
好吧,其实我一直没读懂题。
题目里面说的,刚好有两个牧场(论分不清举例与题目要求的后果)。
这样的话,第一种相对简单的方法就对了。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 const int maxn=155; 7 const double inf=1e12; 8 int n,x[maxn],y[maxn]; 9 double md[maxn],G[maxn][maxn],ans=inf;10 double dis(int i,int j) {11 return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));12 }13 int main() { //细节居多,用心体会,没啥好解释的14 scanf("%d",&n);15 for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]);16 for(int i=1;i<=n;++i)17 for(int j=1;j<=n;++j) G[i][j]=i==j?0:inf;18 char point;19 for(int i=1;i<=n;++i) {20 while((point=getchar())=='\n'||point==' '||point=='\r');21 if(point=='1') G[i][1]=dis(i,1);22 for(int j=2;j<=n;++j) if((point=getchar())=='1') G[i][j]=dis(i,j);23 }24 for(int k=1;k<=n;++k)25 for(int i=1;i<=n;++i)26 for(int j=1;j<=n;++j)27 G[i][j]=min(G[i][j],G[i][k]+G[k][j]);28 for(int i=1;i<=n;++i)29 for(int j=1;j<=n;++j) if(G[i][j]!=inf) md[i]=max(md[i],G[i][j]);30 for(int i=1;i<=n;++i)31 for(int j=1;j<=n;++j) if(G[i][j]==inf) ans=min(ans,md[i]+md[j]+dis(i,j));32 for(int i=1;i<=n;++i) ans=max(ans,md[i]);33 printf("%.6f",ans);34 return 0;35 }
当然,如果牧场不是两个,就相对麻烦一点,可以去参考dalao的题解: