//最小生成樹模板 /* 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; } /**********次小生成樹*********************************/ //次小生成樹最多有一條邊與最小生成樹不一樣,求出最小生成樹後,枚舉不在最小生成樹中的邊u-v, //加入這條邊會造成環,所以再去掉最小生成樹中u-v路徑中的權值最大的邊。 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; int t,n,m,mp[110][110],vis[110],maxl[110][110],dis[110],pre[110],used[110][110]; int Prim(){ memset(maxl,0,sizeof(maxl)); memset(used,0,sizeof(used)); for(int i=1;i<=n;i++){ dis[i]=mp[1][i]; vis[i]=0;pre[i]=1; } vis[1]=1; int ans=0; for(int i=1;i<n;i++){ int minl=inf,sta=-1; for(int j=1;j<=n;j++){ if(!vis[j]&&dis[j]<minl){ minl=dis[j]; sta=j; } } if(sta==-1) return -1; vis[sta]=1; used[sta][pre[sta]]=used[pre[sta]][sta]=1; ans+=minl; for(int j=1;j<=n;j++){ if(vis[j]&&j!=sta) maxl[sta][j]=maxl[j][sta]=max(maxl[pre[sta]][j],dis[sta]); else if(!vis[j]&&dis[j]>mp[sta][j]){ dis[j]=mp[sta][j]; pre[j]=sta; } } } return ans; } int Smst(int ans){ int tmp=inf; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(used[i][j]||mp[i][j]==inf) continue; tmp=min(tmp,ans+mp[i][j]-maxl[i][j]); } } if(tmp==inf) return -1; return tmp; } int main() { return 0; }