最小生成樹與最短路徑樹程式碼
最小生成樹演算法:PRIM和 KRUSKAL
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define MAX_VERTEX_NUM 20
#define OK 1
#define ERROR 0
#define MAX 1000
using namespace std;
typedef struct Arcell
{
double adj;
}Arcell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
char vexs[MAX_VERTEX_NUM]; //節點陣列
AdjMatrix arcs; //鄰接矩陣
int vexnum, arcnum; //圖的當前節點數和弧數
}MGraph;
typedef struct Pnode //用於普利姆演算法
{
char adjvex; //節點
double lowcost; //權值
}Pnode, Closedge[MAX_VERTEX_NUM]; //記錄頂點集U到V-U的代價最小的邊的輔助陣列定義
typedef struct Knode //用於演算法中儲存一條邊及其對應的2個節點
{
char ch1; //節點1
char ch2; //節點2
double value;//權值
}Knode, Dgevalue[MAX_VERTEX_NUM];
//-----------------------------------------------------------------------------------
int CreateUDG(MGraph & G, Dgevalue & dgevalue);
int LocateVex(MGraph G, char ch);
int Minimum(MGraph G, Closedge closedge);
void MiniSpanTree_PRIM(MGraph G, char u);
void Sortdge(Dgevalue & dgevalue, MGraph G);
//-----------------------------------------------------------------------------------
int CreateUDG(MGraph & G, Dgevalue & dgevalue) //構造無向加權圖的鄰接矩陣
{
int i, j, k;
cout << "請輸入圖中節點個數和邊/弧的條數:";
cin >> G.vexnum >> G.arcnum;
cout << "請輸入節點:";
for (i = 0; i<G.vexnum; ++i)
cin >> G.vexs[i];
for (i = 0; i<G.vexnum; ++i)//初始化陣列
{
for (j = 0; j<G.vexnum; ++j)
{
G.arcs[i][j].adj = MAX;
}
}
cout << "請輸入一條邊依附的定點及邊的權值:" << endl;
for (k = 0; k<G.arcnum; ++k)
{
cin >> dgevalue[k].ch1 >> dgevalue[k].ch2 >> dgevalue[k].value;
i = LocateVex(G, dgevalue[k].ch1);
j = LocateVex(G, dgevalue[k].ch2);
G.arcs[i][j].adj = dgevalue[k].value;
G.arcs[j][i].adj = G.arcs[i][j].adj;
}
return OK;
}
int LocateVex(MGraph G, char ch) //確定節點ch在圖G.vexs中的位置
{
int a;
for (int i = 0; i<G.vexnum; i++)
{
if (G.vexs[i] == ch)
a = i;
}
return a;
}
//typedef struct Pnode //用於普利姆演算法
//{
// char adjvex; //節點
// double lowcost; //權值
//}Pnode,Closedge[MAX_VERTEX_NUM]; //記錄頂點集U到V-U的代價最小的邊的輔助陣列定義
void MiniSpanTree_PRIM(MGraph G, char u)//普利姆演算法求最小生成樹
{
int i, j, k;
Closedge closedge;
k = LocateVex(G, u);
for (j = 0; j<G.vexnum; j++)
{
if (j != k)
{
closedge[j].adjvex = u;
closedge[j].lowcost = G.arcs[k][j].adj;
}
}
closedge[k].lowcost = 0;
for (i = 1; i<G.vexnum; i++)
{
k = Minimum(G, closedge);
cout << "(" << closedge[k].adjvex << "," << G.vexs[k] << "," << closedge[k].lowcost << ")" << endl;
closedge[k].lowcost = 0;
for (j = 0; j<G.vexnum; ++j)
{
if (G.arcs[k][j].adj < closedge[j].lowcost)
{
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j].adj;
}
}
}
}
int Minimum(MGraph G, Closedge closedge) //求closedge中權值最小的邊,並返回其頂點在vexs中的位置
{
int i, j;
double k = 1000;
for (i = 0; i<G.vexnum; i++)
{
if (closedge[i].lowcost != 0 && closedge[i].lowcost < k)
{
k = closedge[i].lowcost;
j = i;
}
}
return j;
}
int mini = 0;//樹最小代價
void MiniSpanTree_KRSL(MGraph G, Dgevalue & dgevalue)//克魯斯卡爾演算法求最小生成樹
{
int p1, p2, i, j;
int bj[MAX_VERTEX_NUM]; //標記陣列
for (i = 0; i<G.vexnum; i++) //標記陣列初始化
bj[i] = i;
Sortdge(dgevalue, G);//將所有權值按從小到大排序
for (i = 0; i<G.arcnum; i++)
{
p1 = bj[LocateVex(G, dgevalue[i].ch1)];
p2 = bj[LocateVex(G, dgevalue[i].ch2)];
if (p1 != p2)
{
cout << "(" << dgevalue[i].ch1 << "," << dgevalue[i].ch2 << "," << dgevalue[i].value << ")" << endl;
mini += dgevalue[i].value;
for (j = 0; j<G.vexnum; j++)
{
if (bj[j] == p2)
bj[j] = p1;
}
}
}
}
void Sortdge(Dgevalue & dgevalue, MGraph G)//對dgevalue中各元素按權值按從小到大排序
{
int i, j;
double temp;
char ch1, ch2;
for (i = 0; i<G.arcnum; i++)
{
for (j = i; j<G.arcnum; j++)
{
if (dgevalue[i].value > dgevalue[j].value)
{
temp = dgevalue[i].value;
dgevalue[i].value = dgevalue[j].value;
dgevalue[j].value = temp;
ch1 = dgevalue[i].ch1;
dgevalue[i].ch1 = dgevalue[j].ch1;
dgevalue[j].ch1 = ch1;
ch2 = dgevalue[i].ch2;
dgevalue[i].ch2 = dgevalue[j].ch2;
dgevalue[j].ch2 = ch2;
}
}
}
}
void main()
{
int i, j;
MGraph G;
char u;
Dgevalue dgevalue;
CreateUDG(G, dgevalue);
cout << "圖的鄰接矩陣為:" << endl;
for (i = 0; i<G.vexnum; i++)
{
for (j = 0; j<G.vexnum; j++)
cout << G.arcs[i][j].adj << " ";
cout << endl;
}
cout << "請輸入起始點:\n";
cin >> u;
cout << "=============普利姆演算法===============\n";
cout << "構成最小代價生成樹的邊集為:\n";
MiniSpanTree_PRIM(G, u);
cout << "============克魯斯科爾演算法=============\n";
cout << "構成最小代價生成樹的邊集為:\n";
MiniSpanTree_KRSL(G, dgevalue);
printf("樹最小代價為:");
printf("%d\n",mini);
}
樣例:
最短路徑樹演算法:Dijkstra
#include <iostream>
#include <climits>
using namespace std;
#define MAX_VERTEX_NUM 20 // 頂點數量上限
typedef char VerType; // 頂點結構 , 頂點的字母名稱
typedef int ArcType; // 邊的結構 , 權值
typedef enum { DG, UDG } GKind; // 圖型別,{有向圖,無向圖}
// 圖的儲存結構
typedef struct
{
int verNum, arcNum; // 頂點數量, 邊數量
GKind kind; // 圖型別
VerType vertex[MAX_VERTEX_NUM]; //頂點
ArcType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邊
}Graph;
void CreateGraphByArray(Graph &G); // 建立圖G (通過預定義的陣列)
int VertexLoc(const Graph &G, const VerType &v); // 獲取頂點v在圖G中的位置
void ShortestPath_Dijkstra(Graph &G, int k); // 最短路徑演算法 (迪傑斯特拉演算法)
int main()
{
Graph G;
CreateGraphByArray(G);
ShortestPath_Dijkstra(G, 0);
return 0;
}
void CreateGraphByArray(Graph &G)
{
G.kind = DG;
const int vn = 5;
VerType V[vn + 1] = { "12345" };
const int en = 7;
VerType V1[en + 1] = { "1122345" }; //表示點1到2的距離為2;1到5的距離為10···
VerType V2[en + 1] = { "2535456" };
ArcType E[en] = { 2,10,3,7,4,5,6};
// 輸入頂點
G.verNum = vn;
for (int i = 0; i < G.verNum; ++i) {
G.vertex[i] = V[i];
}
// 初始化鄰接矩陣
for (int vi = 0; vi < G.verNum; ++vi) {
for (int vj = 0; vj < G.verNum; ++vj) {
G.arcs[vi][vj] = INT_MAX;
}
}
// 輸入邊
G.arcNum = en;
for (int i = 0; i < G.arcNum; ++i) {
VerType &v1 = V1[i], &v2 = V2[i];
ArcType &e = E[i];
int vi = VertexLoc(G, v1), vj = VertexLoc(G, v2);
if (vi == G.verNum || vj == G.verNum) {
continue;
}
if (UDG == G.kind) {
G.arcs[vi][vj] = G.arcs[vj][vi] = e;
}
else {
G.arcs[vi][vj] = e;
}
}
}
int VertexLoc(const Graph &G, const VerType &v)
{
for (int i = 0; i < G.verNum; ++i) {
if (G.vertex[i] == v) {
return i;
}
}
return G.verNum;
}
void ShortestPath_Dijkstra(Graph &G, int v0)
{
const int N = 5; //此處設定頂點個數********************************
bool S[N]; // 表示v0到vi的最短路徑是否已經確定
int Path[N]; // 表示v0到vi的最短路徑上的直接前驅頂點
long long D[N]; // 表示v0到vi的最短路徑長度
for (int v = 0; v < N; ++v) {
S[v] = false;
D[v] = G.arcs[v0][v];
Path[v] = D[v] != INT_MAX ? v0 : -1;
}
S[v0] = true;
D[v0] = 0;
for (int i = 1; i < N; ++i) {
int min = INT_MAX, v;
for (int w = 0; w < N; ++w) {
if (!S[w] && D[w] < min) {
v = w;
min = D[w];
}
}
if (min != INT_MAX) {
S[v] = true;
for (int w = 0; w < N; ++w) {
if (!S[w] && (D[v] + G.arcs[v][w] < D[w])) {
D[w] = D[v] + G.arcs[v][w];
Path[w] = v;
}
}
}
}
/* 輸出最短路徑 */
for (int vi = 0; vi < N; ++vi) {
cout << "最短路徑:";
cout << G.vertex[vi];
if (S[vi]) {
for (int vj = Path[vi]; vj != -1; vj = Path[vj]) {
cout << "←" << G.vertex[vj];
}
cout << " 距離為:" << D[vi] << endl;
}
else {
cout << " (INF)" << endl;
}
}
}
結果:
相關推薦
最小生成樹與最短路徑樹程式碼
最小生成樹演算法:PRIM和 KRUSKAL #include<stdio.h> #include<stdlib.h> #include<iostream> #define MAX_VERTEX_NUM 20 #defi
最小生成樹與最短路徑--C語言實現
的區別 find 延遲 遍歷 最短路徑 標記 += 創建 png 接昨天,在這裏給出圖的其中一種應用:最小生成樹算法(Prime算法和Kruskal算法)。兩種算法的區別就是:Prime算法以頂點為主線,適合用於頂點少,邊密集的圖結構;Kruskal算法以邊為主線,適合於頂
最小生成樹與最短路徑的區別以及實現方法
一 區別最小生成樹能夠保證整個拓撲圖的所有路徑之和最小,但不能保證任意兩點之間是最短路徑。最短路徑是從一點出發,到達目的地的路徑最小。二 實現方法1. 最小生成樹最小生成樹有兩種演算法來得到:Prims演算法和Kruskal演算法。Kruskal演算法:根據邊的加權值以遞增
圖的最小生成樹 VS 最短路徑
圖的應用問題 note 僅作入門參考的記錄 1. 網路架設之路徑最短問題 參考給出了兩個演算法:Prim 演算法和Kruskal演算法,前者針對鄰接矩陣,後者針對邊集陣列。
求最小生成樹和最短路徑的總結
1.求最小生成樹有兩種方法: ①克魯斯卡爾演算法:這個演算法是以邊為單位(包括邊的所有的資訊:兩個端點+權值)進行儲存的,然後將邊按照權值的從小到大的順序進行排序,然後將第一條邊連線起來,第二條邊連線起來,就這樣一直迴圈,直到所有的邊都被連線起來為止,在這期間,你需要判斷
圖(Graph)——最小生成樹、最短路徑、Kruskal、Dijkstra、Floyd
4. 最小生成樹 4.1 生成樹 (1)定義:所有頂點均由邊連線在一起,但不存在迴路的圖叫該圖的生成樹 (2)深度優先生成樹與廣度優先生成樹 (3) 一個圖可以有許多棵不同的生成樹 所有
資料結構:圖——圖的遍歷、最小生成樹、最短路徑演算法
前言 在這裡,如果大家對圖或者資料結構還不太熟悉,想找一個動態的生成過程來參考,這是一個不錯的網站. 知識框架 圖的定義 線上性結構中,資料元素之間滿足唯一的線性關係,每個資料元素(除第一個和最後一個外)只有一個直接前趨和一個直接後繼; 在樹形結構中,資料元素之間有著明顯的層次關係,
圖的遍歷、最小生成樹、最短路徑
這一篇我們要總結的是圖(Graph),圖可能比我們之前學習的線性結構和樹形結構都要複雜,不過沒有關係,我們一點一點地來總結,那麼關於圖我想從以下幾點進行總結: 1,圖的定義? 2,圖相關的概念和術語? 3,圖的建立和遍歷? 4,最小生成樹和最短路徑? 5,演算法實現? 回到頂部一,圖的定義 什麼
[學習-思考-探究]莫隊算法 曼哈頓最小生成樹與分塊區間詢問算法
所有 我們 轉移 關鍵字 這樣的 不必要 時間復雜度 大於 莫隊算法 前段時間刷了一些莫隊算法的題目,這裏記錄了一些理解和思考。莫隊算法算法莫隊算法用於解決一類可以由區間[l,r]的答案可以快速轉移出區間[l-1,r],[l+1,r],[l,r+1],[l,r-1]的區間離
[學習-思考-探究]莫隊算法 曼哈頓最小生成樹與分塊區間詢問算法-2
iostream using space style 聯系 const ear math 模版 若要轉載,不需要聯系我,只需要在下面回復一下並註明原文。 在線區間詢問算法(增強算法) 考慮保存狀態 例題:小Z的襪子 如果對小Z的襪子應用基礎算法,會發生什麽? 小Z的襪子這道
[學習-思考-探究]莫隊算法 曼哈頓最小生成樹與分塊區間詢問算法-3
tdi push_back col none ast 查找 循環 pac 生成 若要轉載,不需要聯系我,只需要在下面回復一下並註明原文。 在線區間詢問算法(增強算法)2 #include <iostream> #include <algorithm>
BZOJ-4777 Switch Grass(最小生成樹+動態開點線段樹+可刪堆)
題意 給定一張 n n n 和節點,
bzoj 2561: 最小生成樹【最小割】
inf front ostream ring pos clu clas 要求 || 看錯題了以為多組詢問嚇得不行…… 其實還挺好想的,就是數據範圍一點都不網絡流。把U作為s,V作為t,以最小生成樹為例,(U,V,L)要在最小生成樹上,就要求所有邊權比L小的邊不能連通(U,V
POJ-2485 Highways---最小生成樹中最大邊
style ble include void ack return 最小生成樹 color spa 題目鏈接: https://vjudge.net/problem/POJ-2485 題目大意: 求最小生成樹中的最大邊 思路: 是稠密圖,用prim更好,但是規模不大,kru
PKUACM 2018 D Chocolate 最小生成樹 Kruskal 最長公共子序列
size and this put first test case ren The was $ \rightarrow $ 戳我進POJ原題 D:Chocolate 總時間限制: 1000ms $ \quad $ 內存限制: 65536kB 描述 Vincent is
BZOJ 2561 最小生成樹 (最小割)
任重而道遠 給定一個邊帶正權的連通無向圖G=(V,E),其中N=|V|,M=|E|,N個點從1到N依次編號,給定三個正整數u,v,和L (u≠v),假設現在加入一條邊權為L的邊(u,v),那麼需要刪掉最少多少條邊,才能夠使得這條邊既可能出現在最小生成樹上,也可能出現在最大生成樹上? Inp
POJ 2485 - Highways(求最小生成樹的最大權值-Kruskal演算法)
題目 Language:Default Highways Time Limit: 1000MS
最小生成樹求最大比率 UVALive - 5713
題目連結:https://vjudge.net/problem/UVALive-5713 題意:給出t組資料,每組資料第一行給出一個n,表示點的數量,接下來n行,每行有三個數字,分別是點的座標x,y和點的值w。現在我們要用n-1條邊來連線這n個點,秦始皇希望這n-1條邊的權值之和最小,現在徐福說他可以讓其中
最小生成樹之kruskal演算法(附程式碼)
prim演算法是通過找距離最近的節點來擴充最小生成樹的,稠密圖選擇prim演算法效率比較高,但是對於稀疏圖呢,prim演算法就顯的比較雞肋了。對於稀疏圖,有一個叫做kruskal的演算法。此演算法求稀疏圖的效率比較高,時間複雜度為O(ElogE)。 kruskal演算法主要
BZOJ 2177: 曼哈頓最小生成樹 曼哈頓最小生成樹
2177: 曼哈頓最小生成樹 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 281 Solved: 117 [Submit][Status][Discuss] Description 平面座標系xOy內,給定n個頂點