最小生成樹模板

 
//最小生成樹模板
/* 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;
}
相關文章
相關標籤/搜索