0
点赞
收藏
分享

微信扫一扫

最小生成树模板


kruskal:

typedef pair<int, int> pii;
const int N = 600 + 10, M = 2000000 + 10, INF = 0x3f3f3f3f;
struct edge
{
    int v, u, cost;
    friend bool operator< (edge a, edge b)
    {
        return a.cost < b.cost;
    }
}g[N*N];
int cnt;
int par[N], rnk[N];
void init(int n)
{
    cnt = 0;//初始化边集
    for(int i = 1; i <= n; i++) par[i] = i, rnk[i] = 0;
}
int ser(int x)
{
    int r = x, i = x, j;
    while(r != par[r]) r = par[r];
    while(par[i] != r) j = par[i], par[i] = r, i = j;
    return r;
}
void unite(int x, int y)
{
    x = ser(x), y = ser(y);
    if(x == y) return;
    if(rnk[x] > rnk[y]) par[y] = x;
    else
    {
        par[x] = y;
        if(rnk[x] == rnk[y]) rnk[y]++;
    }
}
bool same(int x, int y)
{
    return ser(x) == ser(y);
}
void add_edge(int v, int u, int cost)
{
    cnt++;
    g[cnt].v = v, g[cnt].u = u, g[cnt].cost = cost;
}
int kruskal(int n)
{
    int tot = 0, ans = 0;
    sort(g + 1, g + 1 + cnt);
    for(int i = 1; i <= cnt; i++)
    {
        if(! same(g[i].v, g[i].u))
        {
            unite(g[i].v, g[i].u);
            ans += g[i].cost;
            tot++;
        }
    }
    return tot == n-1 ? ans : -1; //选中的边数不到n-1,说明无生成树
}

prim:

typedef pair<int, int> pii;
const int N = 600 + 10, M = 2000000 + 10, INF = 0x3f3f3f3f;
int g[N][N]; //邻接矩阵存图
int mincost[N];
bool vis[N];
int prim(int n)
{//点下标1~n
    memset(mincost, 0x3f, sizeof mincost);
    memset(vis, 0, sizeof vis);
    mincost[1] = 0;
    int ans = 0, tot = 0;
    while(true)
    {
        int v = -1;
        for(int i = 1; i <= n; i++)
            if(! vis[i] && (v == -1 || mincost[i] < mincost[v])) v = i;
        if(v == -1 || mincost[v] == INF) break;
        vis[v] = true;
        ans += mincost[v];
        tot++;
        for(int i = 1; i <= n; i++) mincost[i] = min(mincost[i], g[v][i]);
    }
    return tot == n ? ans : -1;//选中的点数不到n,说明无生成树
}

二叉堆优化prim:

typedef pair<int, int> pii;
const int N = 600 + 10, M = 2000000 + 10, INF = 0x3f3f3f3f;
struct edge
{
    int to, cost, next;
}g[N*N*2];
int cnt, head[N];
int mincost[N];
bool vis[N];
void init()
{
    cnt = 0;
    memset(head, -1, sizeof head);
}
void add_edge(int v, int u, int cost)
{
    g[cnt].to = u, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++;
}
int prim(int n)
{//点下标1~n
    priority_queue<pii, vector<pii>, greater<pii> > que;
    memset(vis, 0, sizeof vis);
    memset(mincost, 0x3f, sizeof mincost);
    que.push(pii(0, 1)), mincost[1] = 0;
    int ans = 0, tot = 0;
    while(! que.empty())
    {
        int v = que.top().second; que.pop();
        if(vis[v]) continue;
        vis[v] = true;
        tot++;
        ans += mincost[v];
        for(int i = head[v]; i != -1; i = g[i].next)
        {
            int u = g[i].to;
            if(mincost[u] > g[i].cost)
            {
                mincost[u] = g[i].cost;
                que.push(pii(mincost[u], u));
            }
        }
    }
    return tot == n ? ans : -1;//选中的点数不到n,说明无生成树
}


举报

相关推荐

0 条评论