HDU-4081 Qin Shi Huang's National Road System
阿新 • • 發佈:2018-11-02
意思就是先求出最小生成樹,接下來要選一條邊作為magic路徑
要讓這條magic路徑(u,v)的值最大 = (p[u]+p[v]) / 最小生成樹的花費(減去magic路徑後)
先用次小生成樹演算法求出Max陣列,接下來列舉每條邊作為magic路徑
如果這條邊被用到了,它的值就是(p[u]+p[v]) / 最小生成樹的花費-cost[u][v]
如果沒被用到,值就是(p[u]+p[v]) / 最小生成樹的花費-Max[u][v]
取最大值輸出
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=1000+10; const int INF=999999999.9; bool vis[N]; double lowc[N]; int pre[N],p[N]; double Max[N][N],cost[N][N]; bool used[N][N]; double Prim(int n) { double ans=0; memset(vis,false,sizeof(vis)); memset(used,false,sizeof(used)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) Max[i][j]=0.0; for(int i=1;i<n;i++) { lowc[i]=cost[0][i]; pre[i]=0; } pre[0]=-1; vis[0]=true; for(int i=1;i<n;i++) { double minc=INF; int p=-1; for(int j=0;j<n;j++) if(!vis[j]&&minc>lowc[j]) { minc=lowc[j]; p=j; } if(p==-1) return -1.0; ans+=minc; vis[p]=true; used[p][pre[p]]=used[pre[p]][p]=true; for(int j=0;j<n;j++) { if(vis[j]&&j!=p) Max[j][p]=Max[p][j]=max(Max[pre[p]][j],minc); if(!vis[j]&&lowc[j]>cost[p][j]) { lowc[j]=cost[p][j]; pre[j]=p; } } } return ans; } double solve(int n) { double ans=Prim(n); double ret=0.0; for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(cost[i][j]!=INF) { double t; if(!used[i][j]) t=1.0*(p[i]+p[j])/(ans-Max[i][j]); else t=1.0*(p[i]+p[j])/(ans-cost[i][j]); ret=max(ret,t); } return ret; } double x[N],y[N]; double dist(double ax,double ay,double bx,double by) { return sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by)); } int main() { int T,n; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { cost[i][i]=INF; scanf("%lf%lf%d",&x[i],&y[i],&p[i]); for(int j=0;j<i;j++) cost[i][j]=cost[j][i]=dist(x[i],y[i],x[j],y[j]); } printf("%.2f\n",solve(n)); } return 0; }