a.問題描述:實際生活中,我們總須找到最優的情況,如修建道路怎樣才最省錢。我們可以將實際問題看成一張圖,要滿足我們的需求,這張圖有很多種方案,我們要找出對我們來說最優的乙個方案,其他的方案都放棄。那問題就轉化成怎樣構建一顆最小的的樹了。
實現方法有兩種:
1.kruskal演算法:以邊為選擇物件,選擇過程進行貪心選擇,通過並查集實現。適用於稀疏圖。
主要步驟:1.將邊的資訊儲存在結構體陣列中;
2.按照邊權進行排序,小的在前;
3.對邊從前向後依次選擇,如果此邊所關聯的兩點已經聯通則放棄此邊,否則選擇此邊。直到所有邊判斷完&&選夠n-1條邊
**如下:
kruskal:
#include
#include
#include
using
namespace
std;
const
int maxn=1e6+10;
int fa[maxn];
struct edgeedge[maxn];
int findroot(int x)
return r;
}bool union(int x,int y)//對union進行適當改造
return
false;
}bool cmp(edge a,edge b)
}sort(edge+1,edge+n*(n-1)/2+1,cmp);
sum=0;
for(i=1;i<=n*(n-1)/2&&cnt1;++i)//只寫i
}printf("%d\n",sum);
}return
0;}
2.prime演算法:以點為研究物件,將點分成兩個集合:乙個已經確定是最短路,乙個還未確定;用最短路的思路選出n個點。適用於稠密圖。
主要步驟:
1.將圖儲存在臨接矩陣之中(便於訪問是否鄰接);
2.任選一點作為起始點;
3.將此點加入到已確定點集之中;
4.依次點為原點,更新與之相關聯的節點到點集的距離(最小);
5. 選中剩餘點中距離點集最近的點,加入點集,並以其為原點更新和他相鄰接的點的距離………
6. 迴圈,直到點集中有n個點為止。
**如下:
prime:
#include
#include
using
namespace
std;
#define inf 0x3f3f3f //只能這樣定義了 換一種就錯 或者下方這種
//#define inf 0x3f3f3f3f
const
int maxn=1e3+10;
intmap[maxn][maxn],dis[maxn];//儲存圖(頂點鄰接矩陣)和點的距離
bool vis[maxn];//標記是否訪問過
int ans;//儲存答案
void prime(int n)
}vis[k]=true; ans+=top;//將此點加入集合並更新結果
for(int j=1;j<=n;++j)//更新與已選點鄰接節點的距離 }}
}int main()
prime(n);
printf("%d\n",ans);
}return
0;}
詳細講解: 最小生成樹總結
給定一張圖,圖中有許多的節點還有許多長度不同的邊將這些點點相互連線,找出連線所有點的最短方式就是最小生成樹,可以證明,這樣一種最小的情況是不會出現環的,由於所有的無環圖都可以看做樹,所以成為最小生成樹。頂層思想是分治,選擇策略是貪心,實現方法如下 以邊為中心,先將所有的邊從小到大進行排序,之後依照大...
最小生成樹總結
啊,先紀念一下吧,難得一天這麼 666 ac 完了所有題 次小生成樹 看懂 今天學到了最小生成樹演算法中的 prim 演算法和kruskal 演算法。從巨集觀上來講 prim 更適合稠密圖,krustal 更適合稀疏圖,但對於我們來說暫時沒有什麼區別啦。prim 演算法中主要注意的點是 在visit...
最小生成樹總結
研究了一天最小生成樹 衍生出來包括最小瓶頸樹,次小生成樹,最小樹形圖之類的演算法,前兩者基本能搞定,最後那個就。不太懂了日後再回去看吧似乎很少用到,抄個模板以備不時之需 先談談最小瓶頸樹 首先注意這兩個定理 命題 無向圖的最小生成樹一定是瓶頸生成樹。命題 瓶頸生成樹不一定是最小生成樹 好了 知道這個...