最小產生樹,什麼是最小產生樹?
比較官方的定義:設G=(V,E)是一個無向連通帶權圖,即一個網路。E中每條邊(u,v)的權為cost。如果G的子圖G‘是一棵包含G的所有頂點的樹,則稱G’為G的產生樹。產生樹上邊權總和為該產生樹的耗費。在G的所有產生樹中,耗費最小的即為G的最小產生樹。
簡單的說:一個連通圖中,用花費最少的邊使得該圖依然連通。
解決最小產生樹問題,是一個經典的貪心過程。通常有兩種演算法
演算法一:prim。
基本思想:設一個集合S,先取一個點放入集合中,然後枚舉不屬於S且與S中相連的點的邊,取權值最小的邊,這就是最小產生樹中的邊。依次直到取到所有的點,演算法結束。
核心代碼:
int prim()<br />{<br /> int i,j,p;<br /> int minc,res=0;<br /> memset(chk,0,sizeof(chk));<br /> chk[0]=1;<br /> for(i=1;i<n;i++) lowc[i]=cost[0][i];<br /> for(i=1;i<n;i++)<br /> {<br /> minc=inf;<br /> p=-1;<br /> for(j=0;j<n;j++)<br /> if(chk[j]==0 && minc>lowc[j])<br /> {<br /> minc=lowc[j];<br /> p=j;<br /> }<br /> if(inf==minc) return -1;<br /> res+=minc;<br /> chk[p]=1;<br /> for(j=0;j<n;j++)<br /> if(chk[j]==0 && lowc[j]>cost[p][j]) lowc[j]=cost[p][j];<br /> }<br /> return res;<br />}
演算法二:kruskal。
基本思想:首先將G看成n個孤立的連通分支。將所有的邊按從小到大排序。然後從第一條邊開始,如果該邊的兩個頂點不再同一個連通分量裡面,則將他們所在的
兩個連通分量合并,否則檢查下一條邊。直到所有的頂點都在同一個連通分量中,或者所有的邊都遍曆結束。顯然,這裡要用到並查集。
核心代碼:
int fat[N];<br />int rank[N];<br />int n,m;<br />struct line<br />{<br /> int x,y,len;<br />};<br />int cmp(const void *a,const void *b)<br />{<br /> return (*(line*)a).len > (*(line*)b).len ? 1 : -1;<br />}<br />line edge[E];<br />void build()<br />{<br /> int i,a,b,c;<br /> for(i=0;i<m;i++)<br /> {<br /> scanf("%d%d%d",&a,&b,&c);<br /> a--; b--;<br /> edge[i].x=a;<br /> edge[i].y=b;<br /> edge[i].len=c;<br /> }<br /> qsort(edge,m,sizeof(edge[0]),cmp);<br />}<br />void Make_set()<br />{<br /> for(int i=0;i<n;i++)<br /> {<br /> fat[i]=i;<br /> rank[i]=0;<br /> }<br />}<br />int Find_set(int x)<br />{<br /> if(x!=fat[x]) fat[x]=Find_set(fat[x]);<br /> return fat[x];<br />}<br />int Union(int k)<br />{<br /> int x,y;<br /> x=Find_set(edge[k].x);<br /> y=Find_set(edge[k].y);<br /> if(x==y) return 0;<br /> if(rank[x]>rank[y]) fat[y]=x;<br /> else<br /> {<br /> if(rank[x]==rank[y]) rank[y]++;<br /> fat[x]=y;<br /> }<br /> return edge[k].len;<br />}<br />int Kruskal()<br />{<br /> int i,j,ans=0;<br /> Make_set();<br /> for(i=0;i<m;i++) ans+=Union(i);<br /> return ans;<br />}
嗯,就先寫這麼多吧,後面如果還有內容會繼續更新。