先來前排賣個瓜子,推薦個oj:乙個神奇的oj
假設要在n個城市之間建立通訊聯絡網,則連通n個城市只需要n-1條線路。
這時, 如何在最節省經費的前提下建立這個通訊網。
在每兩個城市之間都可以設定—條線路,相應地都要付出一定的經濟代價。
n個城市之間,最多可能設定n(n- 1)/2條線路,那麼,如何在這些可能的線路中選擇n-1條,以使總的耗費最少呢?
這題是裸的最小生成樹,何為最小生成樹?就是一張圖,n個點,n-1條邊,且邊上的權值加起來還要最小
這題的樣例圖如下
(畫圖技術不要吐槽)
這圖的最小生成樹就是
邊上的權值相加就是75,就是最小生成樹了
那麼怎麼知道是這樣一棵樹呢
最小生成樹有兩個做法
1.prim
2.克魯斯卡(英語不行)
我的做法是克魯斯卡的
克魯斯卡的做法就是:
首先是排序邊:
然後將並查集所需要的f陣列初始化
這裡需要自行去查詢並查集的寫法
選取最小的邊,也就是第一條
第一條邊所連線的兩個點是1,2
用並查集查詢1和2的祖先
u=find(1),v=find(2)
發現u不等於v,我們就把他們並在一起即f[v]=u,這樣下次查詢祖先就可以找到同乙個了
然後仿照剛剛的做法就可以把2和5也連線起來
但這裡要記得是把f[5]賦值為2的祖先,即1
3和5的這一條也不多說的,直接上圖
3和4,4和6的這兩條也來了(唉,,圖好多,,這是我畫得最好的圖了)
至此,一棵完美的最小生成樹就完成了
但
比如到了2和3這一條
此時按照剛剛的步驟,它會先找2的祖先u=3,再找3的祖先v=3
這時我們發現兩點已經連通,沒必要再連一次了,所以就不會連了
也就是說判斷是否連通只要判斷u是否等於v
另外咱們選的邊是從最小開始的選取,所以生成的樹自然也就是最小的
用一句話概括:易證其正確性
所以我就不證了,剩下的內容自己腦補吧
如果前面都看懂了,那麼恭喜你學會了最小生成樹,等你**寫多了,你就會發現
這個演算法其實並沒有什麼卵用,,,感覺很少用到的樣子
要想考試拿高分,還得學爆搜啊:)
1 #include 2 #include 3 #include 4 #include 569 通訊線路using
namespace
std;
6int f[300];7
struct
graph
8a[45000
];11
bool
cmp(graph x,graph y)
1215
int find(int
x)16
19int
main()
2036
}37 sort(a+1,a+k,cmp);
38for(i=1;i)
3947
}48 printf("
%d\n
",ans);
49return0;
50 }
kruskal 最小生成樹
include include 產生隨機數組用 include 同上 include using namespace std 1 帶權邊的類myarc class myarc bool operator const myarc arc myarc myarc int beginvex,int end...
最小生成樹Kruskal
最小生成樹有兩個特點,乙個是保證了所有邊的和是最小值,另乙個是保證了所有邊中的最大值最小。struct edge bool friend operator edge a,edge b 構邊 vectoredge int id max int mini void initial void input ...
最小生成樹(kruskal)
kruskal演算法 1 記graph中有v個頂點,e個邊 2 新建圖graphnew,graphnew中擁有原圖中相同的e個頂點,但沒有邊 3 將原圖graph中所有e個邊按權值從小到大排序 4 迴圈 從權值最小的邊開始遍歷每條邊 直至圖graph中所有的節點都在同乙個連通分量中 if 這條邊連線...