数据结构--图(更新中)

摘抄于胡凡的《算法笔记》

一.最小生成树(Minimum Spanning Tree):在一个给定的无向图G中求一棵树T,使得这棵树拥有图G中的边,并且满足整棵树的边权之和最小。

算法核心思想:贪心

1.Krustal算法(边贪心)

(1)对所有的边按边权从小到大进行排序;

(2)按边权从小到大测试所有边,如果当前测试边所连接的两个顶点不在同一个连通块中,则把这条测试边加入当前最小生成树中;否则,将边舍弃;

(3)执行步骤2,直到最小生成树中的边数等于总顶点数减1或是测试完所有边时结束。如果结束时,最小生成树的边数小于总顶点数减1,说明该图不连通。

    判断两个顶点是否在一个连通块中需要用到并查集,查看其根节点是否是同一个,若不是同一个则合并到一个集合中,否则舍弃。

核心代码展示:

#define MAXE 100

struct Edge{
    int u,v;
    int cost;
}E[MAXE];
bool cmp(Edge a,Edge b) { return a.cost<b.cost; } int Father[100];//并查集数组 //查找根节点 int FindFather(int x) { if(x!=Father[x]) return FindFather(Father[x]); return x; } //Krustal函数返回最小生成树的边权之和,参数n为顶点个数,m为图的边数 int krustal(int n,int m) { //ans为所求边权之和,Num_Edge为当前生成树的边数 int ans=0,Num_Edge=0; //并查集初始化 for(int i=1;i<=n;++i) Father[i]=i; //所有的边按边权从小到大排序 sort(E,E+m,cmp); for(int i=0;i<m;++i) { //查询测试边两个端点所在集合的根节点 int faU=FindFather(E[i].u); int faV=FindFather(E[i].v); if(faU!=faV){ Father[faU]=faV; ans+=E[i].cost; Num_Edge++; if(Num_Edge==n-1) break; } } //不是连通的 if(Num_Edge!=n-1) return -1; else return ans; }

时间复杂度:O(ElogE)       其中E为图的边数

                     算法是用于顶点多,边数少的情况。

2.Prim算法

基本思想:对图G(V,E)设置集合S,存放已被访问的顶点,然后每次从集合V-S中选择与集合S的最短距离最小的一个顶点(记为u),访问并加入集合S,之后令u为中介点,优化所有的从u你能到达的顶点v与集合S之间的最短距离。这样的操作执行n次(n为顶点个数),直到集合S已包含所有顶点。

伪代码:

G为图,一般设为全局变量;数组d为顶点与几何S的最短距离
Prim(G,d[]){
    初始化;
    for(循环n次){
        u=使d[u]最小的还未被访问的顶点的标号;
        记u已被访问;
        for(从u出发能到达的所有顶点v){
            if(v未被访问过&&以u为中介点使得v与集合S的最短距离d[v]更优){
                将G[u][v]赋值给v与集合S的最短距离d[v];
            }
        }
    }
}

 

posted @ 2018-10-27 22:45  shenljyw  阅读(185)  评论(0编辑  收藏  举报