树(最小乘积生成树,克鲁斯卡尔算法):BOI timeismoney

The NetLine company wants to offer broadband internet to N towns. For this, it suffices to construct
a network of N-1 broadband links between the towns, with the property that a message can travel
from any town to any other town on this network. NetLine has already identified all pairs of towns
between which a direct link can be constructed. For each such possible link, they know the cost and
the time it would take to construct the link.
The company is interested in minimizing both the total amount of time (links are built one at a time)
and the total amount of money spent to build the entire network. Since they couldn’t decide among
the two criteria, they decided to use the following formula to evaluate the value of a network:
SumTime = sum of times spent to construct the chosen links
SumMoney = sum of the money spent to construct the chosen links
V = SumTime * SumMoney
Task
Find a list of N-1 links to build, which minimizes the value V.
Description of input
The first line of input contains integers N – the number of towns and M – the number of pairs of
towns which can be connected. The towns are numbered starting from 0 to N-1. Each of the next M
lines contain four integers x, y, t and c – meaning town x can be connected to town y in time t and
with cost c.
Description of output
In the first line of output print two numbers: the total time (SumTime) and total money (Sum-
Money) used in the optimal solution (the one with minimal value V), separated by one space. The
next N-1 lines describe the links to be constructed. Each line contains a pair of numbers (x,y) describing
a link to be build (which must be among the possible links described in the input file). The
pairs can be printed out in any order. When multiple solutions exist, you may print any of them.

Constraints

· 1 ≤ N ≤ 200
· 1 ≤ M ≤ 10 000
· 0 ≤ x,y ≤ N-1
· 1 ≤ t,c ≤ 255
· One test has M = N - 1
· 40% of the tests will have for each possible link t = c
Example
timeismoney.in
5 7
0 1 161 79
0 2 161 15
0 3 13 153
1 4 142 183
2 4 236 80
3 4 40 241
2 1 65 92

timeismoney.out

279 501
2 1
0 3
0 2
3 4

  方案啥的很好解决,就不写了。

  和HNOI2014画框有类似的思想。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=210;
 6 const int maxm=10010;
 7 int fa[maxn],a[maxm],b[maxm];
 8 int u[maxm],v[maxm],n,m;
 9
10 struct Node{
11     int x,y,z,id;
12     Node(int a=0,int b=0,int c=0,int d=0){
13         x=a;y=b;z=c;id=d;
14     }
15     friend bool operator <(Node a,Node b){
16         return a.z<b.z;
17     }
18 }p[maxm];
19
20 struct Point{
21     int x,y;
22     Point(int a=0,int b=0){
23         x=a;y=b;
24     }
25     friend bool operator ==(Point a,Point b){
26         return a.x==b.x&&a.y==b.y;
27     }
28 }lo,hi;
29
30 int Find(int x){
31     return fa[x]==x?x:fa[x]=Find(fa[x]);
32 }
33
34 Point Get_Ans(){
35     sort(p+1,p+m+1);Point ret(0,0);
36     for(int i=1;i<=n;i++)fa[i]=i;
37     for(int i=1;i<=m;i++){
38         int x=p[i].x,y=p[i].y;
39         if(Find(x)!=Find(y)){
40             ret.x+=a[p[i].id];
41             ret.y+=b[p[i].id];
42             fa[Find(y)]=Find(x);
43         }
44     }
45     return ret;
46 }
47
48 Point Solve(Point l,Point r){
49     for(int i=1;i<=m;i++)
50         p[i]=Node(u[i],v[i],b[i]*(r.x-l.x)-a[i]*(r.y-l.y),i);
51     Point mid=Get_Ans();
52     if(mid==l||mid==r)return l.x*l.y<r.x*r.y?l:r;
53     l=Solve(l,mid);r=Solve(mid,r);
54     return l.x*l.y<r.x*r.y?l:r;
55 }
56
57 int main(){
58     freopen("timeismoney.in","r",stdin);
59     freopen("timeismoney.out","w",stdout);
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<=m;i++){
62         scanf("%d%d",&u[i],&v[i]);u[i]+=1;v[i]+=1;
63         scanf("%d%d",&a[i],&b[i]);
64     }
65
66     for(int i=1;i<=m;i++)p[i]=Node(u[i],v[i],a[i],i);lo=Get_Ans();
67     for(int i=1;i<=m;i++)p[i]=Node(u[i],v[i],b[i],i);hi=Get_Ans();
68     Point ans=Solve(lo,hi);
69     printf("%d %d\n",ans.x,ans.y);
70     return 0;
71 }
时间: 2024-10-07 19:14:13

树(最小乘积生成树,克鲁斯卡尔算法):BOI timeismoney的相关文章

--最小生成树的处理(始终抓取最小边的克鲁斯卡尔算法)

Consider yourself lucky! Consider yourself lucky to be still breathing and having fun participating inthis contest. But we apprehend that many of your descendants may not have this luxury. For, as youknow, we are the dwellers of one of the most pollu

【最小乘积生成树】bzoj2395[Balkan 2011]Timeismoney

设每个点有x,y两个权值,求一棵生成树,使得sigma(x[i])*sigma(y[i])最小. 设每棵生成树为坐标系上的一个点,sigma(x[i])为横坐标,sigma(y[i])为纵坐标.则问题转化为求一个点,使得xy=k最小.即,使过这个点的反比例函数y=k/x最接近坐标轴. Step1:求得分别距x轴和y轴最近的生成树(点):A.B(分别按x权值和y权值做最小生成树即可). Step2:寻找一个在AB的靠近原点一侧的且离AB最远的生成树C,试图更新答案. [怎么找???? ——由于C离

最小生成树(普利姆算法、克鲁斯卡尔算法)

给定一个加权无向连通图,如何选择一个生成树,使权利的最小总和的边缘所有树,叫最小生成树. 求最小生成树算法 (1) 克鲁斯卡尔算法 图的存贮结构採用边集数组,且权值相等的边在数组中排列次序能够是随意的.该方法对于边相对照较多的不是非常有用,浪费时间. (2) p=1313">普里姆算法 图的存贮结构採用邻接矩阵.此方法是按各个顶点连通的步骤进行,须要用一个顶点集合,開始为空集,以后将以连通的顶点陆续增加到集合中,所有顶点增加集合后就得到所需的最小生成树 . 以下来详细讲下: 克鲁斯卡尔算法

(转)最小生成树之普利姆算法、克鲁斯卡尔算法

 最小生成树之prim算法 边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以把边上的权值解释为线路的造价.则最小生成树表示使其造价最小的生成树. 构造网的最小生成树必须解决下面两个问题: 1.尽可能选取权值小的边,但不能构成回路: 2.选取n-1条恰当的边以连通n个顶点: MST性质:假设G=(V,E)是一个连通网,U是顶点V的一个非空子集.若(

一步一步写算法(之克鲁斯卡尔算法 上)

原文:一步一步写算法(之克鲁斯卡尔算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 克鲁斯卡尔算法是计算最小生成树的一种算法.和prim算法(上,中,下)按照节点进行查找的方法不一样,克鲁斯卡尔算法是按照具体的线段进行的.现在我们假设一个图有m个节点,n条边.首先,我们需要把m个节点看成m个独立的生成树,并且把n条边按照从小到大的数据进行排列.在n条边中,我们依次取出其中的每一条边,如果发现边的两个节点分别位于两棵树上,那么把两

克鲁斯卡尔算法与公交问题

克鲁斯卡尔算法与公交问题 应用场景-公交站问题 类似的 看一个应用场景和问题: 某城市新增7个站点(A, B, C, D, E, F, G) ,现在需要修路把7个站点连通 各个站点的距离用边线表示(权) ,比如 A – B 距离 12公里 问:如何修路保证各个站点都能连通,并且总的修建公路总里程最短? 克鲁斯卡尔算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路 具体做法:首先构造一个只

45. 蛤蟆的数据结构笔记之四十五克鲁斯卡尔算法

本篇名言:"假如生活欺骗了你 ,不要忧郁 , 也不要愤慨 !不顺心的时候暂且容忍 : 相信吧 , 快乐的日子就会到来.--普希金" 上两篇学习了弗洛伊德和迪杰特斯拉算法.这次来看下克鲁斯卡尔算法. 欢迎转载,转载请标明出处:http://write.blog.csdn.net/postedit/47071539 1.  克鲁斯卡尔算法 克鲁斯卡尔(Kruskal)算法是在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边.是实现图的最小生成树最常用的算法.

克鲁斯卡尔算法

环境: Codeblocks 13.12 + GCC 4.7.1 参考资料:<大话数据结构>,<啊哈算法>,百度百科 基本思想:(1)构造一个只含n个顶点,边集为空的子图.若将图中各个顶点看成一棵树的根节点,则它是一个含有n棵树的森林.(2)从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图.也就是说,将这两个顶点分别所在的两棵树合成一棵树:反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之(3)依次类推,直至森

数据结构课程设计-克鲁斯卡尔算法最小生成树

假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{∮}),图中每个顶点自成一个连通分量.在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边.依次类推,直至T中所有顶点都在同一连通分量上为止. (1)根据原图,构造一个只含n个顶点,边集为空的子图.若将图中各个顶点看成一棵树的根节点,则它是一个含有n棵树的森林. (2)从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不