USACO 2.4Cow Tours (最短路)
Posted 水郁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO 2.4Cow Tours (最短路)相关的知识,希望对你有一定的参考价值。
题意:给你n(最多150)个点的坐标,给出邻接矩阵,并且整个图至少两个联通块,现在让你连接一条边,使得所有可联通的两点的最短距离的最大值最小。
题解:先dfs染色,再用floyd跑出原图的直径O($n^3$),然后枚举新增的边的端点O($n^2$),再分别找出到边端点距离最远的点($n$),那么添加这条边后新图的直径要么是原图直径要么就是两个端点到各自最远点的距离之和加上边的长度。每次维护最小的直径。这样总的是O($n^3$)。
代码:
/* TASK:cowtour LANG:C++ */ #include<cstdio> #include<algorithm> #include<cmath> const double INF=0x3f3f3f3f; using namespace std; #define N 155 int n,x[N],y[N],b[N]; int color; double ans; double d[N][N]; double dis(int i,int j){return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));} void dfs(int x){ b[x]=color; for(int i=1;i<=n;i++) if(d[x][i]!=INF&&!b[i]) dfs(i); } 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]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)d[i][j]=INF; for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++){ char c=getchar(); if(c==‘1‘) d[i][j]=dis(i,j); } for(int i=1;i<=n;i++) if(!b[i]){ color++; dfs(i); } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)if(i!=j) if(d[i][j]>d[i][k]+d[k][j]) d[i][j]=d[i][k]+d[k][j]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)if(d[i][j]!=INF) ans=max(ans,d[i][j]); double m=INF; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++)if(b[i]!=b[j]){ double d1=0,d2=0; for(int k=1;k<=n;k++){ if(d[i][k]!=INF) d1=max(d1,d[i][k]); if(d[k][j]!=INF) d2=max(d2,d[k][j]); } m=min(m,d1+d2+dis(i,j)); } printf("%f\n",max(m,ans)); return 0; }
以上是关于USACO 2.4Cow Tours (最短路)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1631 Usaco 2007 Feb. Cow Party
Luogu P2886 [USACO07NOV]牛继电器Cow Relays|最短路,倍增