1.問題
//有乙個連通圖
//圖中有n個點,編號為1到n
//圖中有m條無向邊,格式為a b l 表示a與b之間有一條長為l的邊
//沒有重邊,沒有自環,所有點都相互連通
//求圖的一棵最小生成樹
2.解析
圖的最小生成樹即花費最少路徑長度將圖中所有點連通
有兩種演算法有優秀的時間複雜度解決這類問題
一種是prim演算法,原理是基於貪心思想,先為空圖取乙個起始點,記錄起點與其他點的距離,然後每步都是取圖到其他未在圖內的點的距離中最短的點和距離加入圖中,然後用新加入的點更新圖到其他點的距離,直到所有點加入其中,可得到最優解。
一種是kruskal演算法,原理也是基於貪心思想,將所有邊排序後優先取短的邊,依次取下來直到所有點連通,可得到最優解。
3.設計
/*
10 30
1 2 5
1 3 7
1 5 6
1 6 20
1 8 12
1 9 23
1 10 13
2 4 15
2 5 17
2 6 8
2 7 19
2 9 37
3 5 21
3 4 33
3 8 29
3 7 12
3 10 18
4 7 16
4 10 39
4 6 26
5 7 26
5 9 7
5 10 17
6 7 18
6 8 24
6 10 16
7 8 22
7 10 19
8 9 7
9 10 28
*/int head[110], ecnt = 0;
struct edge ;
edge(int from, int to, int nxt, int val) : from(from), to(to), nxt(nxt), val(val) {};
bool operator < (const edge& a) const
}edge[110 * 10];
inline void add(int u, int v, int w) ; head[u] = ecnt;
edge[++ecnt] = ; head[v] = ecnt;
}bool vis[110];
int dis[110];
int prim(int s, int n)
vis[s] = 1;
while (1)
} if (k == -1) break;
vis[k] = 1; sum += minn;
printf("%d %d\n", k, minn);
for (int i = head[k]; i; i = edge[i].nxt)
} return sum;
}int fa[110];
int find(int x)
void union_(int x, int y)
int kruskal(int n)
if (cnt == n - 1) break;
} return sum;
}int main()
printf("%d\n", prim(1, n));
printf("%d\n", kruskal(n));
}
4.分析
prim演算法
一開始初始化dis陣列複雜度為o(n);
每次加點更新圖的複雜度為兩個o(n)複雜度的迴圈相加為o(2n);
總共要重複加n-1個點,所以總複雜度是t(n) = o(n - 1) * o(2n) + o(n) = o(n^2)
kruskal演算法
對m條邊排序複雜度為o(mlogm);
初始化並查集父親陣列複雜度為o(n);
接下來貪心加邊的迴圈次數複雜度不穩定, 最優為o(n), 最差情況為o(m);
貪心加邊迴圈內使用的是路徑壓縮並查集,其中find函式和union函式複雜度接近o(1);
所以t(n) = o(mlogm) + o(n) + o(m) = o(mlogm)
5.原始碼
course assignment
演算法第一次作業
命名 命名,包括檔名 類名 結構名 型別名 函式名 變數名 引數名等都是程式設計中重要的一部分。乙個好的名稱,體現了乙個深思熟慮的過程,同時也 能夠幫助別人更好地理解開發者的思路。如果發現程式中,充滿了a,b,c,x,y,z,tmp這種命名的變數,這時候就需要仔細的考慮自己的實現是否有問題。類 結構...
演算法分析與設計第一次作業
1.問題 1 舉乙個例項,畫出採用prim演算法構造最小生成樹的過程,並編寫演算法。2 舉乙個例項,畫出採用kruskal演算法構造最小生成樹的過程,並編寫演算法。2.解析 定義無向加權圖的生成樹代價為樹中所有邊的代價 權值 之和。最小代價生成樹是具有最小代價的生成樹。求無向連通圖的最小代價生成樹,...
機器演算法第一次作業
1 貼上python環境及pip list截圖,了解一下大家的準備情況。暫不具備開發條件的請說明原因及打算。3 什麼是機器學習,有哪些分類?結合案例,寫出你的理解。監督學習 supervised learning 表示機器學習的資料是帶標記的,這些標記可以包括資料類別 資料屬性及特徵點位置等。這些標...