啊,先紀念一下吧,難得一天這麼
666 ac
完了所有題 (次小生成樹**看懂)
今天學到了最小生成樹演算法中的
prim
演算法和kruskal
演算法。從巨集觀上來講
prim
更適合稠密圖,
krustal
更適合稀疏圖,但對於我們來說暫時沒有什麼區別啦。
prim
演算法中主要注意的點是
在visit陣列與minn陣列(最小到達某點的權邊的權值)上 注意只有未遍歷而且小於當前所存的權才可以更新
迴圈次數為n-1次,錯誤的次數會導致答案錯誤
除自身為0以外,所有點之間的初始距離為正無窮
kruskal
演算法中主要注意的點是
所有的邊要用結構體存,方便快排
注意並查集的getfather函式的壓縮路徑和union函式的是否父親相同的判斷
注意變數k的維護,k滿足k==n-1時必須及時跳出迴圈
還有乙個很容易忽略的問題!!就是memset,特別是有多組資料的時候必須在前面重置記憶體
附上我對次小生成樹**的注釋:
#include #include #include #include using namespace std;
/* * 次小生成樹
* 求最小生成樹時,用陣列max[i][j]來表示mst中i到j最大邊權
* 求完後,直接列舉所有不在mst中的邊,替換掉最大邊權的邊,更新答案
* 點的編號從0開始
*/const int maxn=110;
const int inf=0x3f3f3f3f;//最大值
bool vis[maxn];//點是否已使用
int lowc[maxn];//到每乙個點權值最短的路徑的權值
int pre[maxn];//存父親
int max[maxn][maxn];//max[i][j]表示在最小生成樹中從i到j的路徑中的最大邊權
bool used[maxn][maxn];//邊是否已使用
int prim(int cost[maxn],int n)
if(minc==inf) return -1;//該圖不是連通圖
ans+=minc;//權值和計算
vis[p]=true;//點已遍歷
used[p][pre[p]]=used[pre[p]][p]=true;//邊已遍歷
for(int j=0;jcost[p][j])}}
return ans;
}int ans;
int smst(int cost[maxn],int n)
int cost[maxn][maxn];
int main()
while(m--)
ans=prim(cost,n);
if(ans==-1)
if(ans==smst(cost,n)) printf("not unique!\n");//權值和完全相同
else printf("%d\n",ans);//輸出最小生成樹的權值和
}return 0;
}
最小生成樹總結
給定一張圖,圖中有許多的節點還有許多長度不同的邊將這些點點相互連線,找出連線所有點的最短方式就是最小生成樹,可以證明,這樣一種最小的情況是不會出現環的,由於所有的無環圖都可以看做樹,所以成為最小生成樹。頂層思想是分治,選擇策略是貪心,實現方法如下 以邊為中心,先將所有的邊從小到大進行排序,之後依照大...
最小生成樹總結
研究了一天最小生成樹 衍生出來包括最小瓶頸樹,次小生成樹,最小樹形圖之類的演算法,前兩者基本能搞定,最後那個就。不太懂了日後再回去看吧似乎很少用到,抄個模板以備不時之需 先談談最小瓶頸樹 首先注意這兩個定理 命題 無向圖的最小生成樹一定是瓶頸生成樹。命題 瓶頸生成樹不一定是最小生成樹 好了 知道這個...
最小生成樹總結
最小生成樹的性質 1 最小生成樹並不唯一,準確的來說是最小生成樹的樹形並不唯一 2 最小生成樹的權值之和唯一,並且是最小的 3 最小生成樹的邊數 頂點數 1 求最小生成樹有兩種經典演算法 普里姆演算法 prim 和克魯斯卡爾 kruskal 演算法 演算法比較 時間複雜度比較 prim在稠密圖中比k...