2013-team4/code/mst

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
三种算法:
1. prim算法,邻接阵形式,O(V^2)
2. Kruskal算法, O(ElogE+Eα(E, V))
3. Boruvka算法, 最坏时间复杂度O((V+E)logV),平均时间复杂度O(V+E)
}}}
{{{
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN=1000+10;
const int MAXM=100000+10;
const int inf=1e9;

struct node {
    int u, v, w;
    int next;
    bool operator < (const node &x) const {
        return w<x.w;
    }
}edge[MAXM];

int f[MAXN];

int getf(int x) {
    return (x==f[x]) ? x : (f[x]=getf(f[x]));
}
//求出無向圖的其中一棵最小(大)生成樹。
//时间复杂度O(N^2)
int prim(int n, int mat[][MAXN], int *pre) {
    int Min[MAXN], ret=0;
    static bool vis[MAXN];
    int i, j, k;
    for (i=0; i<n; i++) Min[i]=inf, vis[i]=false, pre[i]=-1;
    for (Min[j=0]=0; j<n; j++) {
        for (k=-1, i=0; i<n; i++)
            if (!vis[i]&&(k==-1||Min[i]<Min[k]))
                k=i;
        for (vis[k]=1, ret+=Min[k], i=0; i<n; i++)
            if (!vis[i]&&mat[k][i]<Min[i])
                Min[i]=mat[pre[i]=k][i];
    }
    return ret;
}
//求出無向圖的其中一棵最小(大)生成樹。若是圖不連通,則是求出其中一叢最小(大)生成森林。
//时间复杂度O(ElogE+Eα(E, V))
int kruskal(int n, int m) {
    int ret=0;
    for (int i=0; i<n; i++) f[i]=i;
    sort(edge, edge+m);
    for (int i=0; i<m; i++) {
        int u=getf(edge[i].u), v=getf(edge[i].v), w=edge[i].w;
        if (u==v) continue; f[u]=v; ret+=w;
    }
    return ret;
}
//求出無向圖的其中一棵最小(大)生成樹。若是圖不連通,則是求出其中一叢最小(大)生成森林。
//最坏时间复杂度O((V+E)logV),平均时间复杂度O(V+E)
int Boruvka(int n, int m) {
    static int d[MAXN];
    static int e[MAXN];
    for (int i=0; i<n; i++) f[i]=i;
    int ret=0;
    while (1) {
        int cross_edge=0;
        for (int i=0; i<n; i++) d[i]=inf;
        for (int i=0; i<m; i++) {
            int u=getf(edge[i].u), v=getf(edge[i].v), w=edge[i].w;
            if (u==v) continue; cross_edge++;
            if (w<d[u]||(w==d[u]&&i<e[u])) d[u]=w, e[u]=i;
            if (w<d[v]||(w==d[v]&&i<e[v])) d[v]=w, e[v]=i;
        }
        if (cross_edge==0) break;
        for (int i=0; i<n; i++)
            if (d[i]!=inf) {
                int u=getf(edge[e[i]].u), v=getf(edge[e[i]].v);
                if (u==v) continue;
                ret+=edge[e[i]].w; f[u]=v;
            }
    }
    return ret;
}

int main() {
    return 0;
}
}}}
三种算法:
1. prim算法,邻接阵形式,O(V^2)
2. Kruskal算法, O(ElogE+Eα(E, V))
3. Boruvka算法, 最坏时间复杂度O((V+E)logV),平均时间复杂度O(V+E)
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN=1000+10;
const int MAXM=100000+10;
const int inf=1e9;
struct node {
    int u, v, w;
    int next;
    bool operator < (const node &x) const {
        return w<x.w;
    }
}edge[MAXM];
int f[MAXN];
int getf(int x) {
    return (x==f[x]) ? x : (f[x]=getf(f[x]));
}
//求出無向圖的其中一棵最小(大)生成樹。
//时间复杂度O(N^2)
int prim(int n, int mat[][MAXN], int *pre) {
    int Min[MAXN], ret=0;
    static bool vis[MAXN];
    int i, j, k;
    for (i=0; i<n; i++) Min[i]=inf, vis[i]=false, pre[i]=-1;
    for (Min[j=0]=0; j<n; j++) {
        for (k=-1, i=0; i<n; i++)
            if (!vis[i]&&(k==-1||Min[i]<Min[k]))
                k=i;
        for (vis[k]=1, ret+=Min[k], i=0; i<n; i++)
            if (!vis[i]&&mat[k][i]<Min[i])
                Min[i]=mat[pre[i]=k][i];
    }
    return ret;
}
//求出無向圖的其中一棵最小(大)生成樹。若是圖不連通,則是求出其中一叢最小(大)生成森林。
//时间复杂度O(ElogE+Eα(E, V))
int kruskal(int n, int m) {
    int ret=0;
    for (int i=0; i<n; i++) f[i]=i;
    sort(edge, edge+m);
    for (int i=0; i<m; i++) {
        int u=getf(edge[i].u), v=getf(edge[i].v), w=edge[i].w;
        if (u==v) continue; f[u]=v; ret+=w;
    }
    return ret;
}
//求出無向圖的其中一棵最小(大)生成樹。若是圖不連通,則是求出其中一叢最小(大)生成森林。
//最坏时间复杂度O((V+E)logV),平均时间复杂度O(V+E)
int Boruvka(int n, int m) {
    static int d[MAXN];
    static int e[MAXN];
    for (int i=0; i<n; i++) f[i]=i;
    int ret=0;
    while (1) {
        int cross_edge=0;
        for (int i=0; i<n; i++) d[i]=inf;
        for (int i=0; i<m; i++) {
            int u=getf(edge[i].u), v=getf(edge[i].v), w=edge[i].w;
            if (u==v) continue; cross_edge++;
            if (w<d[u]||(w==d[u]&&i<e[u])) d[u]=w, e[u]=i;
            if (w<d[v]||(w==d[v]&&i<e[v])) d[v]=w, e[v]=i;
        }
        if (cross_edge==0) break;
        for (int i=0; i<n; i++)
            if (d[i]!=inf) {
                int u=getf(edge[e[i]].u), v=getf(edge[e[i]].v);
                if (u==v) continue;
                ret+=edge[e[i]].w; f[u]=v;
            }
    }
    return ret;
}
int main() {
    return 0;
}