随笔分类 - 最小生成树
摘要:最小生成树入门题题意:有n个点给出坐标,点和点之间可以用无线电或者卫星通信,每个点都有无线电收发器可进行无线电通信,但是只有m个点有卫星通信功能。卫星通信的距离可以无限大,但无线电通信的距离不能超过D,超过D的部分将使通信费用增加。要使通信费用最少。其实就是求一次最小生成树,m个点有卫星通信,那么就会有m-1条边的通信距离无限大,其实就是这m-1条边不用计算费用。而剩下的边中,找出最大边作为D值,这样剩下的所有的边都不会大于D,那么不会增加通信费用。在构建MST过程中保存下所有的边权值,然后按升序排序,除掉最后的m-1条边(也就是最大的m-1条边,这些边用卫星通信),最大的那条就是D#incl
阅读全文
摘要:最小生成树和这道题是一样的,不过就是给出的数据不同hdu 1879 继续畅通工程说来惭愧,写hdu那个的时候是1Y的,但是写这个却WA了一次是因为整个做法想错了WA的想法是先用邻接矩阵建图,然后用一个had数组记录已经存在的边,在计算MST最小权值的时候如果是已有的边就不用算费用,所以需要adj数组去记录 边的信息但是这个方法显然是错的,因为MST不是唯一的,如果最后MST的总权值最小,但是可能不同的MST用到的已有的边的条数是不同,用到的已有的边最少,那么需要额外付的费用就越好,如果是上面那样做,显然是WA正确的做法就是把已有的边的权值赋值为0或者一个负数都可以(最好是0,那么就不用判断是否
阅读全文
摘要:最小生成树#include <cstdio>#include <cstring>#include <cmath>#define INF 1000000000.0#define N 110double g[N][N],lowcost[N],x[N],y[N];int n,cov[N];double dis(int i , int j){ return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); }int main(){ int T; scanf("%d",&T); w
阅读全文
摘要:最小生成树裸题,给出n个点的坐标,求MST的权值总和,用prim实现#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>#define INF 100000000.0#define N 110using namespace std;double x[N],y[N],dis[N][N],lowcoat[N];bool vis[N];int n;double DIS(int i , int j){ return sqrt( (x[i]-x[j])*(x[i
阅读全文
摘要:判断MST的唯一性用kruskal算法实现,主要利用MST的环性质先保存所有的边在一个边集数组a中,然后单独去构建一个MST,在a中没能用上的非安全边全部放到另一个边集数组b中另外在构建MST过程要构建一个邻接表,用vextor来实现,也就是只统计MST之间的连通情况,非安全边的不统计在内例如 1 2 3(安全边) 1 3 4(非安全边)那么邻接表中,与点1相通的点有点2但是没有点3,因为点3不在MST中,所以在MST中遍历的时候是没办法直接从点1到点3的接下来是就利用MST的环性质,一个MST中不管加入那条非安全边都将会形成一个环。所以我们枚举所有的非安全边,一条非安全边e,(u,v)权值为
阅读全文
摘要:最优比率生成树,网上能找到很多相关的题解和资料,这道题也不是我自己独立完成的,也是看了算法和原理才做出来的相关的知识点有二分,01分数规划,Dinkelbach算法,牛顿迭代法,查阅这些知识点都会对理解这道题有帮助并且能学到新的知识具体的题解就不写了,直接贴找回来的那个讲解,看完基本上都懂了****************************************************解法之一 0-1分数规划设x[i]等于1或0, 表示边e[i]是否属于生成树.则我们所求的比率r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m.
阅读全文
摘要:最小生成树的入门题,和普通裸题有些区别,需要做出一点修改题目是要求两个岛的直接连线要大于等于10小于等于1000而不是说任意两个岛的路径和都是要满足这个条件,否则的话,要满足任意两个岛的路径和满足这个条件还是比较麻烦的显然这道题用prim算法实现才好,因为最多有n*(n-1)/2条边用kruskal算法不好在prim模板中要修改两个地方几个,一个是初始化 for(i=1; i<=n; i++) { adj[i]=1; if(g[1][i]>=MIN) lowcoat[i]=g[1][i]; else lowcoat[i]=INF; } lowcoat[1]=0;原本是直接lowco
阅读全文
摘要:2012-11-23今天复习了一下并查集,然后这道题才发现当时是傻掉了,其实就是并查集找有多少个连通分量,有c个连通分量的话要把他们连起来就需要c-1条边,根本不需要kruskal算法…………………………#include <cstdio>#include <cstring>#define N 1010int p[N];int n,m;int find(int x){ return p[x]==x ? x : p[x]=find(p[x]); }int main(){ while(scanf("%d",&n) && n) { f
阅读全文
摘要://最小生成树裸题,稠密图,用prim实现不用kruskal#include <stdio.h>#include <string.h>#define MAX 110#define INF 1000*100+10int g[MAX][MAX];int n,m;int lowcoat[MAX],adj[MAX];void Prim(){ int i,j,k,min,ans; for(i=1; i<=n; i++) lowcoat[i]=g[1][i] , adj[i]=1; lowcoat[1]=0; for(i=1; i<n; i++) { ...
阅读全文
摘要:最小生成树入门题,和纯粹的裸题有些区别,题目中有些道路已经存在,不需要建造,答案是求最后建造的总费用,不要把已经有的道路的权值算进去//kruskal算法已有的边权植赋为0//用SORT排序,用并查集判断是否成环#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define INF 1236343242#define MAX 110bool vis[MAX][MAX];int p[MAX];int ans[MAX*MAX];struct edge{ in
阅读全文