随笔分类 - 生成树
摘要:前天做题遇到hdu2121 时一点思路都没有,于是往后面一道题去了,结果做了hdu2122(求最小生成树)之后受到启发,hdu2121分明就是一道求有向图的生成树,也就是最小树形图。。。。于是搜了很久,啃了很久,终于……主要在这下面三个博客上学习的:很赞的图,http://hi.baidu.com/bin183/blog/item/45c37950ece4475f1138c273.html很牛逼的理论http://www.zlinkin.com/?p=63很好的模板+题目http://www.notonlysuccess.com/index.php/mst/#more-315pku3164 C
阅读全文
摘要:题意:对一棵树上的点进行实时的增减权值和询问子树的权值和首先:单点修改以及子树查询。对整棵树dfs一遍,记录下欧拉序列。这样有一个好处,就是每一棵子树在这个序列中都是连续的,同时记录下每一棵子树的起始序列号,这样,对子树的查询就变成了一个连续区间的查询了,运用树状数组就可以解决了。那最大生成树呢?“Sailormoon girls want to cut extra branches by using minimum cost, after that..."额,这里要将多余的边减掉,用最小cost,也就是减掉之后,变成了一棵最大生成树。郁闷呀,一开始以为题目所给的cost是没用………
阅读全文
摘要:题意很简单,就是找出一棵最大边值与最小边值差值最小的生成树,首先,从i=0开始枚举以当前边为最小用kruskal 算法求最小生成树,找出最小的差值本来是1A的,不过那个时间500+ms 实在太难接受了,所以一直在剪枝,中间WA了几次,最后,嘻嘻,如愿以偿了,47ms,主要是减少不必要的循环排完序之后,自然是开始枚举生成树的起始边1)若以当前的起始边e[i]用kruskal算法求出的生成树是非联通的,则不用枚举了,因为之后也没法形成联通的生成树了2)在kruskal算法过程中,若出现边值与起始边值的差值大于已求得的最小差值ans,则也可以退出循环了,但还是要继续枚举起始边,退出的是kruskal
阅读全文
摘要:题目描述:给你n个水库,告诉你每个水库的xy坐标(米)和这个水库的花费。如果两个水库需要连接,连接的费用是这两个水库的高度差的绝对值。让你连接一些水库,让所有的水库都能到达1号水库并且只有一条通路(就是一棵树)。然你使每米的花费最少(就是总花费 比 总长度)解题报告:实际上就求一棵最小比率生成树,黑书上介绍的挺详细的,就是在代码实现上有点困难有俩种方法实现,一种是二分法,不过在求上下界方面有点难,并且慢很多,一种是用迭代法,标准的01分数规划,不断的逼近迭代最优解;关于构造式子以及用二分法实现,这个博客上解答的很详细http://hi.baidu.com/zzningxp/blog/item/
阅读全文
摘要:题目大意】给出一个带权无向图,问其最小生成树是否唯一,若唯一输出其权值和,否则输出"Not Unique!".1.其实,在判断最小生成树是否是唯一的时候,用到了次小生成树的思想,求一棵次小生成树,最次小生成树的总权值等于最小生成树的权值,则不唯一;这里涉及到求次小生成树的问题,首先用prim 算法求一个最小生成树, 再做一次添边和删边的操作,添加一条最小生成树外的边,此时必在最小生成树上形成环,在删去环上权值最大的边,求出添删操作中差额最小值,若最小值为0,则不唯一,否则唯一;(这里我是这样做的,在pime算法求最小生成树的过程中,有一个增加生成树节点的操作,每增加一个节点
阅读全文
摘要:这题目郁闷了整整一天,虽然看了黑书上的解释,解题的思路也基本了解,但实现代码仍是一条漫长的路呀算法流程:假设V0为被限制的点,即公园,(1)找{V1,V2,....,Vn}所有的联通分量,求出每个连通分量的最小生成树Ti。(2)在每个连通分量中,选择V0相邻的最小边,得到Ht。Min<--Ht,V<--cost(Ht)。时间复杂度为O(n)。(3)循环i<--t+1 to k do 在H(i-1)上选择“差额最小添加操作”,添加并删除一条边得到Hi,令V<V+cost(添边)-cost(删边), 若V<Min,令Min<--V;如果找不到“差额最小添删操作”
阅读全文
摘要:这来到题目差不多,因为几乎是每条边都用到,所以用prim算法应该会比较好,从运行的效率来看也十分明显hdu1875 则对边做了一定的限制,只需要的加边的时候判断一下就好了hdu 1162 #include<iostream>#include<stdio.h>#include<stdlib.h>#include<string>#include<math.h>#define MAXN 101 #define MAXINT 99999999using namespace std;int n,s[MAXN];double dis[MAXN],
阅读全文
摘要:还是一道差不多一样的最小生成树的题目,数据量本来也不大,Kruskal 算法直接过#include<iostream>#include<string>#include<algorithm>using namespace std;struct edge{ int u,v,w; edge(int x=0,int y=0,int z=0):u(x),v(y),w(z){};};edge e[80];int n,m,ans;int f[30];int find(int x){ if(x==f[x]) return x; f[x]=find(f[x]); return
阅读全文
摘要:hdu1102#include<iostream>#include<string>#define MAXINT 9999999using namespace std;int map[101][101],s[101],dis[101],n;int prim(){ int sum=0; memset(s,0,sizeof(s)); s[1]=1; for(int i=2;i<=n;i++) dis[i]=map[1][i]; dis[1]=0; for(int i=1;i<n;i++) { int min=MAXINT,k=1; for(int j=1;j<
阅读全文
摘要:用Kruskal算法求最小生成树,要用到并查集,最后再顺便用并查集判断是否连通,只需判断父节点数是否唯一#include<iostream>#include<string>#define MAXN 101using namespace std;int n,m,f[MAXN],ans;struct edge{ int u,v,w; edge(int x=0,int y=0,int z=0):u(x),v(y),w(z){};}e[MAXN*50];int cmp(const void *a, const void *b) { if(((struct edge *)a)-&
阅读全文
摘要:prim实现#include<iostream>#include<string>#define MAXINT 9999999using namespace std;int map[101][101],s[101],dis[101],n;int prim(){ int sum=0; memset(s,0,sizeof(s)); s[1]=1; for(int i=2;i<=n;i++) dis[i]=map[1][i]; dis[1]=0; for(int i=1;i<n;i++) { int min=MAXINT,k=1; for(int j=1;j<
阅读全文