HDU4081 Qin Shi Huang's National Road System

这个题还是比较好的,提供了一种求最小生成树不错的方法,但是,C++ TLE,G++  400+ms

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn = 1005;
  7 struct edge
  8 {
  9     int v,next;
 10     double w;
 11 }e[maxn*2];
 12 int head[maxn],cnt;
 13 double d[maxn][maxn];
 14 bool vis[maxn*maxn];
 15 int fa[maxn];
 16 struct EDGE
 17 {
 18     int u,v,p;
 19     double w;
 20 }E[maxn*maxn];
 21 struct node
 22 {
 23     double x,y;
 24     int p;
 25 }a[maxn];
 26 double dis(int i,int j)
 27 {
 28     return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
 29 }
 30 bool cmp(EDGE a,EDGE b)
 31 {
 32     return a.w<b.w;
 33 }
 34 void add(int u,int v,double w)
 35 {
 36     e[cnt].v = v;
 37     e[cnt].w = w;
 38     e[cnt].next = head[u];
 39     head[u] = cnt++;
 40 }
 41 int findd(int x)
 42 {
 43     int rt = x;
 44     while(rt!=fa[rt])rt = fa[rt];
 45     while(x!=rt)
 46     {
 47         int t = fa[x];
 48         fa[x] = rt;
 49         x = t;
 50     }
 51     return rt;
 52 }
 53 int root;
 54 void dfs(int rt,int anc,double dist)
 55 {
 56     d[root][rt] = max(d[root][anc],dist);
 57     for(int i = head[rt];i!=-1;i = e[i].next)
 58         if(e[i].v!=anc)
 59             dfs(e[i].v,rt,e[i].w);
 60 }
 61 int main()
 62 {
 63    // freopen("in.txt","r",stdin);
 64     int T;scanf("%d",&T);
 65     while(T--)
 66     {
 67         int n;scanf("%d",&n);
 68         for(int i = 1;i<=n;++i)scanf("%lf%lf%d",&a[i].x,&a[i].y,&a[i].p);
 69         int m = 0;
 70         for(int i = 1;i<=n;++i)
 71             for(int j = i+1;j<=n;++j)
 72             {
 73                 ++m;
 74                 E[m].u = i;
 75                 E[m].v = j;
 76                 E[m].w = dis(i,j);
 77                 E[m].p = a[i].p+a[j].p;
 78             }
 79         sort(E+1,E+1+m,cmp);
 80         for(int i = 1;i<=n;++i)fa[i] = i;
 81         memset(head,-1,sizeof(head));
 82         for(int i = 1;i<=n;++i)head[i] = -1;
 83         for(int i = 1;i<=m;++i)vis[i] = 0;
 84         cnt = 0;
 85         double MST = 0;
 86         for(int i = 1;i<=m;++i)
 87         {
 88             int fx = findd(E[i].u),fy = findd(E[i].v);
 89             if(fx==fy)continue;
 90             add(E[i].u,E[i].v,E[i].w);
 91             add(E[i].v,E[i].u,E[i].w);
 92             fa[fx] = fy;
 93             vis[i] = 1;
 94             MST += E[i].w;
 95         }
 96         for(int i = 1;i<=n;++i)
 97         {
 98             root = i;
 99             d[root][i] = 0;
100             dfs(i,i,0);
101         }
102         double ans = 0;
103         for(int i = 1;i<=m;++i)
104         {
105             if(vis[i])ans = max(ans,(double)E[i].p/(MST-E[i].w));
106             else ans = max(ans,(double)E[i].p/(MST-d[E[i].u][E[i].v]));
107         }
108         printf("%.2lf\n",ans);
109     }
110     return 0;
111 }

HDU4081 Qin Shi Huang's National Road System

时间: 2024-11-10 13:50:26

HDU4081 Qin Shi Huang's National Road System的相关文章

HDU4081 Qin Shi Huang&#39;s National Road System【Kruska】【次小生成树】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3979    Accepted Submission(s): 1372 Problem Description During the Warring States Period of ancient China(4

HDU4081 Qin Shi Huang&#39;s National Road System(次小生成树)

枚举作为magic road的边,然后求出A/B. A/B得在大概O(1)的时间复杂度求出,关键是B,B是包含magic road的最小生成树. 这么求得: 先在原图求MST,边总和记为s,顺便求出MST上任意两点路径上的最长边d[i][j]. 当(u,v)是magic road时, 如果它在原本的MST上,则B就等于s-原(u,v)的权,而原(u,v)的权其实就是d[u][v]: 如果它不在原本的MST上,则B就等于s-d[u][v]+0. 总之就是一个式子:B=s-d[u][v]. 于是,在

hdu4081 Qin Shi Huang&#39;s National Road System 次小生成树

先发发牢骚:图论500题上说这题是最小生成树+DFS,网上搜题解也有人这么做.但是其实就是次小生成树.次小生成树完全当模版题.其中有一个小细节没注意,导致我几个小时一直在找错.有了模版要会用模版,然后慢慢融会贯通.我要走的路还长着啊. 讲讲次小生成树的思想吧.首先,在prim算法中做一些改变,求出任意两点(u,v)路径之间的最大权值,并记录,记为maxe[u][v].运行遍prim算法.枚举每一条边,如果该边是属于最小生成树的边,则ratio=(value(u) +value(v) ) /( a

HDU4081 Qin Shi Huang&#39;s National Road System 【次小生成树】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3395    Accepted Submission(s): 1189 Problem Description During the Warring States Period of ancient China(4

HDU4081 Qin Shi Huang&#39;s National Road System【prim最小生成树+枚举】

先求出最小生成树,然后枚举树上的边,对于每条边"分别"找出这条割边形成的两个块中点权最大的两个 1.由于结果是A/B,A的变化会引起B的变化,两个制约,无法直接贪心出最大的A/B,故要通过枚举 2.不管magic road要加在哪里,加的边是否是最小生成树上的边,都会产生环,我们都要选择一条边删掉 注意删掉的边必须是树的环上的边,为了使结果最大,即找出最大的边 3.可以枚举两点,找出边,也可以枚举边,找出点,我是用后者,感觉比较容易写也好理解 #include <cstdio&g

HDU-4081 Qin Shi Huang&#39;s National Road System(最小生成树)

今天比赛AC的一道最小生成树的题目 , 学到了不少东西 . 最小生成树的模板很简单,最简洁好写的还是lrj紫书上的代码 .利用并查集加速算法 . 该题的不同之处在于它选择任意一条路修成"魔法"道路 , 然后其他路的权值之和还要是最小的一棵次小生成树,并且求魔法道路两端点值之和除以其他路径长之和的最大值 . 显然该题的难点在于枚举两个端点之后怎么快速的求出次小生成树权值之和 .  枚举两个端点之后的复杂度已经是O(n^2),所以要想出一个快速的方法 . 受紫书上例题uva 1151 (传

HDU 4081 Qin Shi Huang&#39;s National Road System

https://vjudge.net/problem/HDU-4081 题意: 秦始皇想要修长城,修成生成树的样子,这是一个大师出现了,他说他可以不耗费人力修出一条路来.他们的目的很不一样,神特么有分歧,最后他们达成了一个协议,假设一个城市的人口为a.那么最后不耗费人力修的那条路所相连的两个城市的人力之和A与修路花费的人力B之比 A/B最大,并且输出最大值. 思路: 枚举去掉每一条边. 首先求出最小生成树,对于最小生成树中的每一条边,如果这条边不花费人力,那么直接计算A和B就可以了. 那么问题是

HDU 4081 Qin Shi Huang&#39;s National Road System 最小生成树

分析: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> #incl

hdu 4081 Qin Shi Huang&#39;s National Road System(最小生成树+dp)

同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游方道士突然出现,他说他可以不消耗任何人力财力,使用法术凭空造一条路,路的长度无所谓,但是只能造一条.那么问题来了,徐福希望将两座人口数最多的城市连接起来,而秦始皇希望将最长的路修好.最后折中了一下, 将A/B最大的一条路用法术修出来.其中A是两座城市的人口和,B是除了用法术修的路以外,其它需要修建的