生成树

Prim算法

const int inf = 0x3f3f3f;
const int maxn = (300 + 10);

bool vis[maxn];
int lowc[maxn];
int cost[maxn][maxn];

int Prim(int n){
    int ans = 0;
    memset(vis,false,sizeof(vis));
    vis[0] = true;
    for(int i = 1;i < n;i++)    lowc[i] = cost[0][i];
    for(int i = 1;i < n;i ++){
        int minc = inf;
        int p = -1;
        for (int j = 0; j < n; j++) {
            if (!vis[j] && minc > lowc[j]) {
                minc = lowc[j];
                p = j;
            }
        }
        if (minc == inf)    return -1;
        ans += minc;
        vis[p] = true;
        for (int j = 0; j < n; j++) {
            if (!vis[j] && lowc[j] > cost[p][j]) {
                lowc[j] = cost[p][j];
            }
        }
    }
    return ans;
}

Kruskal算法

const int inf = 1000000000;
const int maxn = (1000 + 10);


struct Edge{
    int u,v;
    int w;
    Edge(){}
    Edge(int _u,int _v,int _w){
        u = _u;
        v = _v;
        w = _w;
    }
}edge[maxn * maxn];

bool cmp(Edge a,Edge b){
    return a.w < b.w;
}

int Map[maxn];
int t = 0;

int find(int x){
    if(Map[x] == -1)    return x;
    return Map[x] = find(Map[x]);
}

int Kruskal(int n){
    memset(Map,-1,sizeof(Map));
    sort(edge,edge + t,cmp);
    int cnt = 0;
    int ans = 0;
    for(int i = 0;i < t;i ++){
        int u = edge[i].u;
        int v = edge[i].v;
        int w = edge[i].w;
        u = find(u);
        v = find(v);
        if(u != v){
            ans += w;
            Map[u] = v;
            cnt ++;
        }
        if(cnt == n - 1)    break;
    }
    if(cnt < n - 1) return -1;
    return ans;
}

次小生成树Prim

求出来的依旧是最小的,再根据Max[][]数组求次小生成树

bool vis[maxn];
int lowc[maxn];
int pre[maxn];
int Max[maxn][maxn];
bool used[maxn][maxn];

int cost[maxn][maxn];

int Prim(int n) {
    int ans = 0;
    memset(vis,false,sizeof(vis));
    memset(Max,0,sizeof(Max));
    memset(used,false,sizeof(used));
    vis[0] = true;
    pre[0] = -1;
    for(int i = 1; i < n; i++) {
        lowc[i] = cost[0][i];
        pre[i] = 0;
    }
    lowc[0] = 0;
    for(int i = 1; i < n; i ++) {
        int minc = inf;
        int p = -1;
        for (int j = 0; j < n; j++) {
            if (!vis[j] && minc > lowc[j]) {
                minc = lowc[j];
                p = j;
            }
        }
        if (minc == inf)    return -1;
        ans += minc;
        vis[p] = true;
        used[p][pre[p]] = used[pre[p]][p] = true;
        for (int j = 0; j < n; j++) {
            if(vis[j] && j != p) Max[j][p] = Max[p][j] = max(Max[j][pre[p]],lowc[p]);
            if (!vis[j] && lowc[j] > cost[p][j]) {
                lowc[j] = cost[p][j];
                pre[j] = p;
            }
        }
    }
    return ans;
}

最小树形图

struct Edge{
    int u,v;
    int cost;
}edge[maxm];

int pre[maxn],id[maxn],visit[maxn],in[maxn];
int zhuliu(int root,int n,int m,Edge edge[]){
    int res = 0,u, v;
    while(1){
        for(int i = 0;i < n;i ++)   in[i] = inf;
        for(int i = 0;i < m;i ++){
            if(edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v]){
                pre[edge[i].v] = edge[i].u;
                in[edge[i].v] = edge[i].cost;
            }
        }
        for(int i = 0;i < n; i++){
            if(i != root && in[i] == inf)   return -1;
        }
        int tn = 0;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        for(int i = 0;i < n;i ++){
            res += in[i];
            v = i;
            while(visit[v] != i && id[v] == -1 && v != root){
                visit[v] = i;
                v = pre[v];
            }
            if(v != root && id[v] == -1){
                for (int u = pre[v]; u != v; u = pre[u])
                    id[u] = tn;
                id[v] = tn++;
            }
        }
        if(tn == 0) break;
        for(int i = 0;i < m;){
            v = edge[i].v;
            edge[i].u = id[edge[i].u];
            edge[i].v = id[edge[i].v];
            if(edge[i].u != edge[i].v)  edge[i ++].cost -= in[v];
            else        swap(edge[i],edge[--m]);
        }
        n = tn;
        root = id[root];
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值