分析:http://www.cnblogs.com/wally/archive/2013/02/04/2892194.html
这个题就是多一个限制,就是求包含每条边的最小生成树,这个求出原始最小生成树然后查询就好了
然后预处理那个数组是O(n^2)的,这样总时间复杂度是O(n^2+m)
这是因为这个题n比较小,如果n大的时候,就需要路径查询了,比如LCA 或者树链剖分达到O(mlogn)
#include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <stack> #include <queue> #include <cmath> #include <vector> using namespace std; const int N=1005; double x[N],y[N],d[N][N],a[N]; int fa[N],head[N],tot,cnt,T,n; struct Edge{ int v,next; double w; }edge[N<<1]; void add(int u,int v,double w){ edge[tot].v=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } struct Node{ int u,v; bool mark; double w; bool operator<(const Node &rhs)const{ return w<rhs.w; } }p[N*N]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } int s; void dfs(int u,int f,double t){ d[s][u]=t; for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].v; if(v==f)continue; dfs(v,u,max(t,edge[i].w)); } } int main() { scanf("%d",&T); while(T--){ scanf("%d",&n); cnt=tot=0; memset(d,0,sizeof(d)); for(int i=1;i<=n;++i){ fa[i]=i,head[i]=-1; scanf("%lf%lf%lf",&x[i],&y[i],&a[i]); for(int j=1;j<i;++j){ ++cnt; p[cnt].u=i,p[cnt].v=j;p[cnt].mark=0; p[cnt].w=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } } sort(p+1,p+1+cnt); int tmp=n; double mst=0,ans=0; for(int i=1;i<=cnt;++i){ int u=find(p[i].u),v=find(p[i].v); if(u!=v){ --tmp; fa[u]=v; mst+=p[i].w; p[i].mark=1; add(p[i].u,p[i].v,p[i].w); add(p[i].v,p[i].u,p[i].w); if(tmp==1)break; } } for(int i=1;i<=n;++i){ s=i;dfs(i,0,0); } for(int i=1;i<=cnt;++i){ double aa=a[p[i].u]+a[p[i].v],bb; if(p[i].mark)bb=mst-p[i].w; else bb=mst-d[p[i].u][p[i].v]; ans=max(ans,aa/bb); } printf("%.2f ",ans); } return 0; }