码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-11-04 17:02:01      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   color   ar   os   使用   

Qin Shi Huang‘s National Road System

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

【Problem Description】
During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all six other kingdoms and became the first emperor of a unified China in 221 BC. That was Qin dynasty ---- the first imperial dynasty of China(not to be confused with the Qing Dynasty, the last dynasty of China). So Ying Zheng named himself "Qin Shi Huang" because "Shi Huang" means "the first emperor" in Chinese.
bubuko.com,布布扣
Qin Shi Huang undertook gigantic projects, including the first version of the Great Wall of China, the now famous city-sized mausoleum guarded by a life-sized Terracotta Army, and a massive national road system. There is a story about the road system: There were n cities in China and Qin Shi Huang wanted them all be connected by n-1 roads, in order that he could go to every city from the capital city Xianyang. Although Qin Shi Huang was a tyrant, he wanted the total length of all roads to be minimum,so that the road system may not cost too many people‘s life. A daoshi (some kind of monk) named Xu Fu told Qin Shi Huang that he could build a road by magic and that magic road would cost no money and no labor. But Xu Fu could only build ONE magic road for Qin Shi Huang. So Qin Shi Huang had to decide where to build the magic road. Qin Shi Huang wanted the total length of all none magic roads to be as small as possible, but Xu Fu wanted the magic road to benefit as many people as possible ---- So Qin Shi Huang decided that the value of A/B (the ratio of A to B) must be the maximum, which A is the total population of the two cites connected by the magic road, and B is the total length of none magic roads. Would you help Qin Shi Huang? A city can be considered as a point, and a road can be considered as a line segment connecting two points.
【Input】
The first line contains an integer t meaning that there are t test cases(t <= 10). For each test case: The first line is an integer n meaning that there are n cities(2 < n <= 1000). Then n lines follow. Each line contains three integers X, Y and P ( 0 <= X, Y <= 1000, 0 < P < 100000). (X, Y) is the coordinate of a city and P is the population of that city. It is guaranteed that each city has a distinct location.
【Output】
For each test case, print a line indicating the above mentioned maximum ratio A/B. The result should be rounded to 2 digits after decimal point.
【Sample Input】
2
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40

【Sample Output】

65.00
70.00

【题意】

秦国有n个城市构成,每个城市都有一定的人口。现在要修路,要求最终修成的路花费最少代价使得所有的城市都连通。然后修路的时候可以使用一个魔法,免去一条路的费用,最终结果要使使用了魔法的那条路两端的城市总人口数除以剩下所有路的长度最大。

【分析】
最少代价使得所有点都连通,很容易能够想到最小生成树。
从最终答案是A/B入手,要使这个结果最大,但是明显A与B的大小会互相影响,故不符合贪心的要求。所以采用的只能是枚举每一条边,在指定A的前提下,使B最小。
考虑一下删边是两种情况:
1. i,j边恰好在最小生成树上,那么直接删掉;
2. i,j边不在最小生成树上,那么要在最小生成树中找到i,j路径上最长的边删去;
由于本题完全图的特殊性,如果i,j边在最小生成树上,那么i,j边直接就是路径上的最长边了,也即问题转化为给定两个点,要求在最小生成树上找到两个点路径上最长的边。
而这恰好是求解次小生成树的方法。
 
思路:
按照次小生成树的求法,在Prim的过程中就顺便把路径上的最长边记录下来。Kruskal也可以完成,但是在记录最长边的过程中,Prim是有序扩展,故复杂度会更低。
 
bubuko.com,布布扣
  1 /* ***********************************************
  2 MYID    : Chen Fan
  3 LANG    : G++
  4 PROG    : 4081
  5 ************************************************ */
  6 
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <algorithm>
 11 #include <queue>
 12 #include <cmath>
 13 #include <bitset>
 14 
 15 using namespace std;
 16 
 17 typedef struct pnod
 18 {
 19     int x,y,p;
 20 } pnode;
 21 pnode p[1010];
 22 
 23 typedef struct nod
 24 {
 25     int a,b;
 26     double c;
 27     friend bool operator < (nod a,nod b)
 28     {
 29         return a.c>b.c;
 30     }
 31 } node;
 32 
 33 node edge[1000010];
 34 int start[1010],num[1010];
 35 
 36 bool op(node a,node b)
 37 {
 38     if (a.a==b.a) return a.c<b.c;
 39     else return a.a<b.a;
 40 }
 41 
 42 node ntoh(int a,int b,double c)
 43 {
 44     node x;
 45     x.a=a;
 46     x.b=b;
 47     x.c=c;
 48     return x;
 49 }
 50 
 51 double maxx[1010][1010];
 52 bitset<1010> inway[1010];
 53 
 54 double prim(int s,int n)
 55 {
 56     /**/
 57     int list[1010],listail=1;
 58     list[1]=s;
 59     /**/
 60     priority_queue<node> heap;
 61     while (!heap.empty()) heap.pop();
 62     bitset<1010> flag;
 63     flag.reset();
 64     flag[s]=1;
 65     double ans=0;
 66     memset(maxx,0,sizeof(maxx));
 67     for (int i=0;i<num[s];i++) heap.push(edge[start[s]+i]);
 68 
 69     for (int i=1;i<n;i++)
 70     {
 71         node now=heap.top();
 72         heap.pop();
 73         while (flag[now.b])
 74         {
 75             now=heap.top();
 76             heap.pop();
 77         }
 78         /**/
 79         for (int j=1;j<=listail;j++) 
 80         {
 81             maxx[list[j]][now.b]=max(maxx[list[j]][now.a],now.c);
 82             maxx[now.b][list[j]]=maxx[list[j]][now.b];
 83         }
 84         listail++;
 85         list[listail]=now.b;
 86         /**/
 87         flag[now.b]=true;
 88         ans+=now.c;
 89         for (int j=0;j<num[now.b];j++)
 90         if (!flag[edge[start[now.b]+j].b]) heap.push(edge[start[now.b]+j]);
 91     }
 92 
 93     return ans;
 94 }
 95 
 96 double getdis(int x,int y)
 97 {
 98     return sqrt((p[x].x-p[y].x)*(p[x].x-p[y].x)+(p[x].y-p[y].y)*(p[x].y-p[y].y));
 99 }
100 
101 int main()
102 {
103     freopen("4081.txt","r",stdin);
104 
105     int t;
106     scanf("%d",&t);
107     for (int tt=1;tt<=t;tt++)
108     {
109         int n;
110         scanf("%d",&n);
111         for (int i=1;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].p);
112 
113         int m=0;
114         for (int i=1;i<=n;i++)
115         {
116             start[i]=m+1;
117             num[i]=n-1;
118             for (int j=1;j<=n;j++)
119             if (i!=j)
120             {
121                 m++;
122                 edge[m].a=i;
123                 edge[m].b=j;
124                 edge[m].c=getdis(i,j);
125             }
126         }
127         
128         double sum=prim(1,n);
129 
130         double ma=0;
131         for (int i=1;i<=m;i++)
132         {
133             double temp=(p[edge[i].a].p+p[edge[i].b].p)/(sum-maxx[edge[i].a][edge[i].b]);
134             if (ma<temp) ma=temp;
135         }
136 
137         printf("%.2f\n",ma);
138     }
139 
140     return 0;
141 }
View Code

 

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

标签:des   style   blog   http   io   color   ar   os   使用   

原文地址:http://www.cnblogs.com/jcf94/p/4073961.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!