题意:

  秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B最大。问A/B最大是多少?(1000个城市)

思路:

  老徐可免费修得1条路,那么剩下最多也只需要修n-2条路了,这n-2条路要尽量挑短的,而老徐的那条无所谓长短,只要两城人口尽量多即可。这是没有什么贪心策略的,因为老徐所修之路会影响MST的权值之和的大小。穷举所有城市对要O(n*n),再求次MST需要O(n*n),不可行。

  换个思路,如果能先求得MST,然后穷举要老徐所要修的路,那么在加上老徐的路之后,必然会有个环的出现,这个环中有一条边是不需要的,当然不是老徐那条。这只需要在原MST中求这个环的最小瓶颈路就行了,将其删掉,加上老徐的路,构成新的MST了,进行求值。穷举老徐所要修的路也要O(n*n),那么求瓶颈路就只能用O(1)了。这可以预处理出任意城市对之间的最小瓶颈路,O(n*n)而已。

  任意点对的最小瓶颈路的求法:对原图求最小生成树,只留下树边,树中任意点对之间的路径就是该点对的最小瓶颈路。接着对树图进行DFS,在DFS过程中,顺便求出任意点对的最小瓶颈路,考虑求当前节点x到其他点的最小瓶颈路,设其父亲far,那么x可以通过far到达前面已经访问过的节点,为maxcost[已访问过的节点][far]与cost[far][x]其中的大者。按此思路,在DFS过程中可以求出任意点对的最小瓶颈路。

 #include <bits/stdc++.h>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL long long
using namespace std;
const int N=;
int a[N], b[N], seq[N]; //求MST用的
int x[N], y[N], p[N]; //所给的坐标及人口数
int pre[N], vis[N], used[N]; //求任意点对最小瓶颈路用的
double w[N], maxcost[][]; //两点间的最小瓶颈maxcost
vector<int> vect[N]; //建树时用
vector<int> dfn; //记录访问过的节点 int cmp(int a,int b){return w[a]<w[b];}
int find(int x){return pre[x]==x? x: pre[x]=find(pre[x]);} //并查集
double dis(int a,int b){return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));} void DFS(int x)
{
dfn.push_back(x); //访问过
vis[x]=;
for(int i=; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(!vis[t] )
{
for(int j=; j<dfn.size(); j++) //对于所有已经访问过的节点
{
int from=dfn[j];
maxcost[t][from]=maxcost[from][t]=max(maxcost[from][x], dis(x, t) );//通过x连到t
}
DFS(t);
}
}
} void init(int n) //一堆初始化。
{
dfn.clear();
for(int i=; i<=n; i++) vect[i].clear(),pre[i]=i;
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
maxcost[i][j]=0.0;
memset(used, , sizeof(used));
memset(vis, , sizeof(vis));
}
double cal(int n, int m)
{
init(n);
double sum=0.0; //MST
for(int i=; i<m; i++) //kruscal求最小生成树
{
int u=find(a[seq[i]]);
int v=find(b[seq[i]]);
if( u!=v )
{
pre[u]=v; //不是同个连通块,则连接。
vect[a[seq[i]]].push_back( b[seq[i]] ); //顺便建图,方便建树
vect[b[seq[i]]].push_back( a[seq[i]] );
used[seq[i]]=;
sum+=w[seq[i]];
}
} DFS(); //求任意点对间的最小瓶颈路
double ans=0.0;
for(int i=; i<m; i++) //穷举徐福声将要建的边。
{
double A=p[a[i]]+p[b[i]], B; if(used[i]) B=sum-w[i]; //树上的边
else B=sum-maxcost[a[i]][b[i]];
ans=max( A/B, ans );
}
return ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t, n;
cin>>t;
while(t--)
{
cin>>n;
for(int i=; i<=n; i++) scanf("%d%d%d",&x[i],&y[i],&p[i]);
int cnt=;
for(int i=; i<=n; i++) //求两点间的距离,共n*(n-1)/2条边
{
for(int j=i+; j<=n; j++)
{
a[cnt]=i;
b[cnt]=j;
w[cnt]=dis(i,j);
seq[cnt]=cnt; //千万不要用seq[cnt]=cnt++;或者seq[cnt++]=cnt。
cnt++;
}
}
sort(seq, seq+cnt, cmp); //按边长排序
printf("%.2f\n", cal(n, cnt));
} return ;
}

AC代码

UVALive 5713 Qin Shi Huang's National Road System秦始皇修路(MST,最小瓶颈路)的更多相关文章

  1. UValive 5713 Qin Shi Huang's National Road System

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  2. UVALive 5713 Qin Shi Huang's National Road System(次小生成树)

    题意:对于已知的网络构建道路,使城市两两之间能够互相到达.其中一条道路是可以免费修建的,问需要修建的总长度B与免费修建的道路所连接的两城市的人口之和A的比值A/B最大是多少. 因为是求A/B的最大值, ...

  3. LA 5713 - Qin Shi Huang's National Road System(HDU 4081) MST

    LA:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. 【最小生成树】UVA1494Qin Shi Huang's National Road System秦始皇修路

    Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven ki ...

  5. uvalive 5731 Qin Shi Huang’s National Road System

    题意: 秦始皇要修路使得所有的城市连起来,并且花费最少:有一个人,叫徐福,他可以修一条魔法路,不花费任何的钱与劳动力. 秦始皇想让修路的费用最少,但是徐福想要受益的人最多,所以他们经过协商,决定让 A ...

  6. hdu 4081 Qin Shi Huang's National Road System (次小生成树)

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  7. hdu 4081 Qin Shi Huang's National Road System (次小生成树的变形)

    题目:Qin Shi Huang's National Road System Qin Shi Huang's National Road System Time Limit: 2000/1000 M ...

  8. HDU 4081 Qin Shi Huang's National Road System 次小生成树变种

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  9. Qin Shi Huang's National Road System HDU - 4081(树形dp+最小生成树)

    Qin Shi Huang's National Road System HDU - 4081 感觉这道题和hdu4756很像... 求最小生成树里面删去一边E1 再加一边E2 求该边两顶点权值和除以 ...

随机推荐

  1. Delphi托盘类 收集

    收集的两个托盘程序: 1. 托盘区就是在windows的状态栏下方显示时钟.输入法状态的地方, 要把你的程序显示在托盘区: 下面是一个托盘类,只要把下面粘贴到文本文件中,改成TrayIcon.pas, ...

  2. 运行时修改TimerTask的执行周期

    java.util.TimerTask类的执行周期period变量的声明如下: /** * Period in milliseconds for repeating tasks. A positive ...

  3. (转)Fibonacci Tilings

    Fibonacci numbers {Fn, n ≥ 0} satisfy the recurrence relation (1) Fn+2 = Fn+1 + Fn, along with the i ...

  4. C# virtual和override

    本文转载来自于:http://bollaxu.iteye.com/blog/1662855 在函数的声明中,当有“virtual”修饰的时候,和没有virtual有什么区别呢?最重要的一点就是调用实例 ...

  5. Windows启动系统程序命令

    DEVMGMT.MSC - Device Manager 设备管理器 DISKMGMT.MSC - Disk Management 磁盘管理   WindowsXP常用命令http://baike.b ...

  6. ExtJs布局之viewport

    <!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...

  7. BZOJ 1046: [HAOI2007]上升序列 LIS -dp

    1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3438  Solved: 1171[Submit][Stat ...

  8. poj 1733(带权并查集+离散化)

    题目链接:http://poj.org/problem?id=1733 思路:这题一看就想到要用并查集做了,不过一看数据这么大,感觉有点棘手,其实,我们仔细一想可以发现,我们需要记录的是出现过的节点到 ...

  9. TCP三次握手和四次挥手协议

    相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助. TCP三次握手   所谓三次握手( ...

  10. Android 核心分析 之六 IPC框架分析 Binder,Service,Service manager

    IPC框架分析 Binder,Service,Service manager 我首先从宏观的角度观察Binder,Service,Service Manager,并阐述各自的概念.从Linux的概念空 ...