zoukankan      html  css  js  c++  java
  • 最小生成树(kruskal算法)+prim算法

    题目描述

    如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

    输入格式

    第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

    接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

    输出格式

    输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

    输入输出样例

    输入 #1
    4 5
    1 2 2
    1 3 2
    1 4 3
    2 3 4
    3 4 3
    输出 #1
    7

    说明/提示

    时空限制:1000ms,128M

    数据规模:

    对于20%的数据:N<=5,M<=20

    对于40%的数据:N<=50,M<=2500

    对于70%的数据:N<=500,M<=10000

    对于100%的数据:N<=5000,M<=200000

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int inf=200000;
    struct node{
        int u,v,w;
    }; 
    struct node e[inf];
    int n,m,f[inf],sum=0,cnt=0;
    bool cmp(node t1,node t2)
    {
        return t1.w<t2.w;
    }
    int find(int x)
    {
        if(x!=f[x])
        return f[x]=find(f[x]);
        else
        return x;
    }
    int merge(int x,int y)
    {
        int x1=find(x);
        int y1=find(y);
        if(x1!=y1)
        {
            f[y1]=x1;
            return 1;
        }
        return 0;
    }
    int main()
    {
        int t1,t2;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        f[i]=i;
        for(int i=1;i<=m;i++)
        {
        cin>>e[i].u>>e[i].v>>e[i].w;
        merge(e[i].u,e[i].v);
        }
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(f[i]==i)
            cnt++;
        }
        if(cnt!=1)
        {
            cout<<cnt<<endl;
            cout<<"orz"<<endl;
            return 0;
        }
        for(int i=1;i<=m;i++)
        f[i]=i;
        cnt=0;
        sort(e+1,e+m,cmp);
        for(int i=1;i<=m;i++)
        {
            if(merge(e[i].u,e[i].v))
            {
                cnt++;
                sum=sum+e[i].w;
            }
            if(cnt==n-1)
            {
                break;
            }
        }
        cout<<sum<<endl;
        return 0;
    }

    从边开始找

    first 给所有的边从小到大排序

    找的边要满足这样的条件 边的两点属于不同的连通分量(使用并查集)

    找到n-1条边就行了

    这就是克鲁斯卡尔算法

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int inf=20000;
    int e[inf][inf],dis[inf],book[inf],n,m,sum=0,cnt=0,f[inf]; 
    int find(int x)
    {
        if(x!=f[x])
        return f[x]=find(f[x]);
        else
        return x;
    }
    int merge(int x,int y)
    {
        int x1=find(x);
        int y1=find(y);
        if(x1!=y1)
        {
            f[y1]=x1;
            return 1;
        }
        return 0;
    }
    int main()
    {
        int a,b,c,flag;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        f[i]=i;
        fill(e[0],e[0]+inf*inf,inf);
        fill(dis,dis+inf,inf);
        fill(book,book+inf,0);
        book[1]=1;
        for(int i=1;i<=m;i++)
            {
                e[i][i]=0;
            }
        for(int i=1;i<=m;i++)
        {
            cin>>a>>b>>c;
            e[a][b]=c;
            e[b][a]=c;
            merge(a,b);
        }
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(find(i)==i)
            cnt++;
        }
        if(cnt!=1)
        {
            cout<<cnt<<endl;
            cout<<"orz"<<endl;
            return 0;
        }
        for(int i=1;i<=n;i++)
            dis[i]=e[1][i];
        cnt=1;
        while(cnt<n)
        {
            int minn=inf;
            for(int i=1;i<=n;i++)
            {
                if(book[i]==0&&dis[i]<minn)
                {
                    minn=dis[i];
                    flag=i;
                }
            }
            sum=sum+dis[flag];
            cnt++;
            book[flag]=1;
            for(int j=1;j<=n;j++)
            {
                if(book[j]==0&&dis[j]>e[flag][j])
                {
                    dis[j]=e[flag][j];
                }
            }
        }
        cout<<sum<<endl;
        return 0;
     } 

    prim算法

    将图中的点分成两部分 选入的与未选入的

    从任意的一点出发,出发点加入选入的部分,选出连接选入的部分与未选入的部分的最小的边,并将其加入选入的部分

    则连接最小边的点也加入选入的部分,重复n-1次完成

    很多人说它很像dijkstra算法

    我看这就是dijkstra算法

    如果你够坚强够勇敢,你就能驾驭他们
  • 相关阅读:
    Android图像格式类及图像转换方法
    Java实现文件的加密与解密
    Google最新截屏案例详解
    Android应用程序模拟手机按键
    Android浮动小球与开机自启动
    Android手机截屏
    Android图片浏览器之图片删除
    Android图片浏览器之缩略图
    MFC实现Gif动画制作工具
    QRadioButton分组且无边框的简单实现
  • 原文地址:https://www.cnblogs.com/liuzhaojun/p/11280457.html
Copyright © 2011-2022 走看看