zoukankan      html  css  js  c++  java
  • 最小生成树

    例题

    https://www.luogu.com.cn/problem/P3366

     方法一:prim算法

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    using namespace std;
    #define maxn 5001
    #define inf 0x3f3f3f3f
    int n, m;
    int edges[maxn][maxn];
    int ecost[maxn];
    
    int prim()
    {
        int allcount = 0;
        ecost[1] = 0;//不使用vis数组来标记是否访问过,而是使用ecost【】=0表示该节点已经加入到了最小生成树中
        for (int i = 2; i <= n; i++)
        {
            ecost[i] = edges[1][i];
        }
    
        int mins = inf, mini = -1;
        for (int i = 2; i <= n; i++)
        {
            mins = inf, mini = -1;
            for (int j = 1; j <= n; j++)
            {
                if (ecost[j] != 0 && ecost[j] < mins)
                {
                    mins = ecost[j]; mini = j;
                }
            }
            if (mini == -1)return -1;
            allcount += ecost[mini];
            ecost[mini] = 0;
            for (int j= 2; j <= n; j++)
            {
                if (ecost[j]!=0 && edges[mini][j] < ecost[j])
                    ecost[j] =edges[mini][j] ;
            }
    
        }
        return allcount;
    }
    
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                edges[i][j] = inf;
        for (int i = 0; i < m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
             if (edges[a][b] != 0)//这里看输入实例发现存在重边(1 2 300 ;1 2 500; 2 1 700  应该取300)
            {
                if(c<edges[a][b])
                    edges[a][b] = edges[b][a] = c;
            }
            else edges[a][b] = edges[b][a] = c;
                if (a == b)
                edges[a][b] = edges[b][a] = 0;
        }
        int answer = prim();
        if (answer == -1)printf("orz");
        else printf("%d", answer);
    
    }

    注意事项:要在输入的时候提前处理重边的情况  注意edge数组要进行初始化为INF !!!!!

    使用链式前向星:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    using namespace std;
    #define maxn 5001
    #define maxm 200005
    #define inf 0x3f3f3f3f
    int n, m,cnt=0;
    
    int ecost[maxn],head[maxn];
    struct edge
    {
        int to;
        int dis;
        int next;
    }e[maxm*2];
    
    void addedge(int u, int v, int w)
    {
        cnt++;
        e[cnt].to = v;
        e[cnt].dis = w;
        e[cnt].next = head[u];
        head[u] = cnt;
    }
    
    int prim()
    {
        int allcount = 0;
        for (int i = 1; i <= n; i++)
        {
            ecost[i] = inf;
        }
        ecost[1] =0;
        for (int i = head[1]; i; i = e[i].next)
        {
            int y = e[i].to;
            ecost[y] = min(ecost[y],e[i].dis);//这里进行了去除重边的判断
        }
    
        int mins = inf, mini = -1;
        for (int i = 2; i <= n; i++)
        {
            mins = inf, mini = -1;
            for (int j = 1; j <= n; j++)
            {
                if (ecost[j] != 0 && ecost[j] < mins)
                {
                    mins = ecost[j]; mini = j;
                }
            }
            if (mini == -1)return -1;
            allcount += ecost[mini];
            ecost[mini] = 0;
            for (int i = head[mini]; i; i = e[i].next)
            {
                int  y = e[i].to;
                if (ecost[y] != 0 && ecost[y] > e[i].dis)
                    ecost[y] = e[i].dis;
            }
    
        }
        return allcount;
    }
    
    
    int main()
    {
        scanf("%d%d", &n, &m);
        
        for (int i = 0; i < m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            addedge(a, b, c);
            addedge(b, a, c);
        }
        int answer = prim();
        if (answer == -1)printf("orz");
        else printf("%d", answer);
    
    }

    法二:kruskal算法

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    using namespace std;
    #define maxn 5001
    #define maxm 200005
    #define inf 0x3f3f3f3f
    int n, m, cnt = 0,allcount=0;
    
    int ecost[maxn], father[maxn];
    struct edge
    {
        int to;
        int dis;
        int from;
    }e[maxm];
    bool cmp(struct edge&a, struct edge &b)
    {
        return a.dis < b.dis;
    }
    
    
    int find(int x)
    {
        if (x == father[x])return x;
        return father[x] = find(father[x]);
    }
    int kruskal()
    {
        sort(e, e + m, cmp);
        for (int i = 0; i <m; i++)//一共m条边。一条一条判断
        {
            int tempa, tempb;
            tempa = find(e[i].from); tempb = find(e[i].to);
            if (tempa == tempb)continue;
            allcount += e[i].dis;
            father[tempa] = tempb;    
        }
    
        return allcount;
    }
    
    
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++)
            father[i] = i;
        for (int i = 1; i <=m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            e[cnt].from = a; e[cnt].to = b; e[cnt].dis = c;
            cnt++;
        }
        int answer = kruskal();
        if (answer == -1)printf("orz");
        else printf("%d", answer);
    
    }
  • 相关阅读:
    linux查看硬件信息的方法
    linux最常用命令
    研究php单例模式实现数据库类
    HTML5语义元素
    第一次博客作业
    2020系统综合实践 第7次实践作业 06组
    2020系统综合实践 第6次实践作业 06组
    2020系统综合实践 第5次实践作业
    2020系统综合实践 第4次实践作业
    2020系统综合实践 第3次实践作业
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/13171474.html
Copyright © 2011-2022 走看看