標籤:ring for find div clu i++ std namespace 資料
//最小產生樹模板/* kruskal演算法,把所有的邊從小到大排序,接下來從小到大考查每條邊(u,v); 1.u和v在同一個連通分量中,那麼加入(u,v)後會形成環,因此不能選擇。 2.如果u和v在不同的聯通分量中,那麼加入(u,v)一定是最優的。*/#include<iostream>#include<cstring>#include<algorithm>using namespace std;int fat[102];//存放父節點struct Lu{ int u,v,w;};bool cmp(Lu x,Lu y) {return x.w<y.w;}//排序函數int find(int x) {return fat[x]==x?x:find(fat[x]);}//並查集,找根節點int main(){ for(int i=0;i<=100;i++)//初始化並查集 fat[i]=i; sort(L,L+k,cmp);//給邊排序 for(int i=0;i<k;i++) { int x=find(L[i].u),y=find(L[i].v); if(x!=y) //不在同一個並查集,合并 { fat[y]=x; sum+=L[i].w;//權值加 } } return 0;}************************************************************************/* prim演算法,任選一點s放到S集合中,從不在S集合中的點中選出一個點j使得其與S中的某點i的距離最短, 則(i,j)就是產生樹的一條邊,加入S中。繼續按照上面找。資料量較大時用prim方便。*///prim 模板。這題資料太大用cruscal會逾時。#include<iostream>#include<cstdio>#include<cstring>int dis[502],map[502][502],mark[502];const int MAX=10000007;int prim(int n){ for(int i=1;i<=n;i++) //初始化每個點到產生樹中點的距離 { dis[i]=map[1][i]; mark[i]=0; } mark[1]=1; //1這個點加入產生樹中。 int sum=0; for(int i=1;i<n;i++) //枚舉n-1條邊 { int sta=-1,Min=MAX; for(int j=1;j<=n;j++) //找不在產生樹中的點中距離產生樹中的點長度最小的 { if(!mark[j]&&dis[j]<Min) { Min=dis[j]; sta=j; } } if(sta==-1) return -1; //沒找到可以可以聯通的路 mark[sta]=1; //新找到的點加入產生樹 sum+=Min; for(int j=1;j<=n;j++) //更新樹外的點到樹中的點的距離 { if(!mark[j]&&dis[j]>map[sta][j]) dis[j]=map[sta][j]; } } return sum;}int main(){ return 0;}
最小產生樹模板