标签:
题目链接:传送门
题意:
有n坐城市,知道每坐城市的坐标和人口。现在要在所有城市之间修路,保证每个城市都能相连,并且保证A/B 最大,所有路径的花费和最小,A是某条路i两端城市人口的和,B表示除路i以外所有路的花费的和(路径i的花费为0).
分析:
先求一棵最小生成树,然后枚举每一条最小生成树上的边,删掉后变成两个生成树,然后找两个集合中点权最大的两
个连接起来。这两个点中必然有权值最大的那个点,所以直接从权值最大的点开始dfs。
为了使A/B的值最大,则A尽可能大,B尽可能小。所以B中的边一定是MST上去掉一条边后的剩余所有边。首先用O(N^2)算出
MST,然后依次枚举,删去MST上的每一条边,MST变成两棵树T1和T2,然后在剩余的边(即不在MST上的边),以及这条删
去的边中找到该边的两点的权值和最大以及能够连接T1和T2的边,A=删去边后的替换边的两点的权值和,B=删去该边后的MST
的值,求A/B最大。则A尽可能大,A分别是T1和T2中最大的两个点,则所有点中权值最大的点一定在A中,由此在MST上从权值
最大的点作为root,开始dfs。递归求出子树中的每个最大的点以及求出A/B的比值,求出最大。
分析转载自:传送门
我的理解,首先很明显我们是需要求出最小生成树的,然后我们可以枚举边(u,v)中的边,很明显枚举的边都会
与原来MST中的边形成一个环,因为这个边不在MST中,那么这个边的权值一定是大于MST中连接U,V的边的,因此
我们在这个环里去掉的应该是权值最大的边。
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> using namespace std; const int maxn = 1e3+10; const int inf = 1e9+10; struct point{ int x,y; }a[maxn]; int head[maxn],par[maxn],peo[maxn]; bool vis[maxn]; int ip,mmax; double ans ,mst; struct tree{ int u,v; double w; tree(){} tree(int _u,int _v,double _w):u(_u),v(_v),w(_w){} bool operator < (const struct tree &tmp)const{ return w<tmp.w; } }mp[maxn*maxn]; struct nod{ int to,next; double w; }edge[maxn*2]; double calu(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void add(int u,int v,double w){ edge[ip].to=v; edge[ip].w=w; edge[ip].next=head[u]; head[u]=ip++; } int find_par(int x){ if(x!=par[x]) return par[x]=find_par(par[x]); return par[x]; } bool Union(int x,int y){ x=find_par(x); y=find_par(y); if(x!=y){ par[x]=y; return true; } return false; } void init(){ for(int i=0;i<maxn;i++) par[i]=i; ip=mmax=0; ans=mst=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); } int dfs(int root){ vis[root]=1; int peo_max=peo[root]; for(int i=head[root];i!=-1;i=edge[i].next){ int v=edge[i].to; if(!vis[v]){ int tmp = dfs(v); peo_max=max(peo_max,tmp); ans=max(ans,(tmp+mmax)/(mst-edge[i].w)); } } return peo_max; } int main(){ int t,n,root; scanf("%d",&t); while(t--){ init(); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&peo[i]); if(peo[i]>mmax){ mmax=peo[i]; root=i; } } int cnt = 0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ mp[cnt++]=tree(i,j,calu(a[i],a[j])); } } sort(mp,mp+cnt); for(int i=0;i<cnt;i++){ if(Union(mp[i].u,mp[i].v)){ mst+=mp[i].w; add(mp[i].u,mp[i].v,mp[i].w); add(mp[i].v,mp[i].u,mp[i].w); } } dfs(root); printf("%.2lf\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 4081 Qin Shi Huang's National Road System(最小生成树/次小生成树)
标签:
原文地址:http://blog.csdn.net/bigbigship/article/details/46853117