图论板子 最小生成树

kruskal算法 前向星+并查集 需排序(加边,还有一种加点的prim算法,不惯用,就不更了

排序后每次找权值最小的两节点组成的边,加入树,通过并查集确定公共祖先,若某边加入会出现环,跳过,直至所有点都加入树,该树即为最小生成树

板子

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int, int> pr;
typedef long long ll;
#define fi first
#define se second
#define me(x) memset(x, -1, sizeof(x))
#define mem(x) memset(x, 0, sizeof(x))
#define MAXN 500000+5
#define NIL -1
struct node
{
    int u, v, w;
}edge[MAXN];
bool cmp(node a, node b)
{
    if(a.w==b.w && a.u==b.u) return a.v<b.v;
    if(a.w==b.w) return a.u<b.u;
    return a.w<b.w;
}
int p[MAXN];//存祖先  记录每个点的前导点
int ans, n, m;

int Find(int x) //查找根节点
{
    int r=x;
    while(p[r]!=r) //根节点的上级节点为本身
        r=p[r];
    //r为根节点
    int i=x, j;
    while(p[i]!=r)//until p[p[i]]==r 路径压缩 不断更新i的上级节点为根节点
    {
        j=p[i];

        p[i]=r;   //r为根

        i=j;
    }             // 1 --> 3 --> 4 --> 5
    return r;
}

int mix() //合并 联通
{
    for(int i=0; i<m; i++)
    {
        int fx=Find(edge[i].u), fy=Find(edge[i].v);
        if(fx!=fy)
            ans+=edge[i].w, p[fx]=fy;
    }
}
int main()
{
    int i, j, k;
    while(cin>>n>>m)
    {
        ans=0;
        for(i=1; i<=n; i++)
            p[i]=i;        //初始化每个点的父节点为本身
        for(i=0; i<m; i++)
            cin>>edge[i].u>>edge[i].v>>edge[i].w;
        sort(edge, edge+m, cmp);
        mix();
        cout<<ans<<endl;
    }
}

 POJ 2421 Constructing Roads

模板题

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
typedef long long  ll;
#define me(x) memset(x, -1, sizeof(x))
#define mem(x) memset(x, 0, sizeof(x))
const int MOD = 1e18;
const int N = 2e6 + 5;
int a[1005][1005], vis[1005][1005];
struct node
{
    int u, v, d;
}e[N];
int p[N];
int n, m, id, ans;
void ini()
{
    id=0;
    mem(vis);
}
void add(int u, int v, int d)
{
    e[id].u = u;
    e[id].v = v;
    e[id].d = d;
    id++;
}
bool cmp(node a, node b)
{
    if(a.d==b.d && a.u==b.u) return a.v<b.v;
    else if(a.d==b.d) return a.u<b.u;
    else return a.d<b.d;
}
int Find(int x)
{
    int r=x;
    while(r!=p[r])
    {
        r=p[r];
    }
    int i=x, t;
    while(r!=p[i])
    {
        t=p[i];
        p[i]=r;
        i=t;
    }
    return r;
}
void join()
{
    for(int i=0; i<id; i++)
    {
        int x=Find(e[i].u), y=Find(e[i].v);
        if(x!=y)
        {
            p[x]=y;
            ans+=e[i].d;
        }
    }

}
int main()
{
    int i, j, k;
    int t;
    scanf("%d", &n);
        int u, v, d;
        ini();
        for(i=1; i<=n; i++)
        {
            p[i]=i;
            for(j=1; j<=n; j++)
                scanf("%d", &a[i][j]);
        }
        scanf("%d", &m);
        for(i=0; i<m; i++)
            scanf("%d%d", &u, &v), a[u][v]=a[v][u]=0;
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            if(i!=j) add(i,j,a[i][j]);
        sort(e, e+id, cmp);
        ans=0;
        join();
        printf("%d
", ans);
}
View Code
原文地址:https://www.cnblogs.com/op-z/p/11281738.html