【模板】最小生成树

P3366 【模板】最小生成树

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出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

样例解释:

所以最小生成树的总边权为2+2+3=7

p算法代码:(错了,哪位大佬帮我看看!)

#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 5001
#define maxn 1234567
using namespace std;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘) f=-1;
        ch=getchar();
    }
    while(ch<=‘9‘&&ch>=‘0‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return f*x;
}
int n,m,x,y,z,a[N][N],dis[N],ans;
bool b[N];
int main()
{
    memset(b,false,sizeof(b));
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        a[x][y]=a[y][x]=z;
    }
    memset(dis,127,sizeof(dis));
    b[1]=true;
        dis[1]=0;
    for(int i=1;i<=n;i++)
     if(a[1][i])
      dis[i]=min(dis[i],a[1][i]);
    for(int i=1;i<n;i++)
    {
        int maxd=0;
        for(int j=1;j<=n;j++)
        {
            if(!b[j])
             if(maxd==0||dis[j]<dis[maxd])
              maxd=j;
        }
        ans+=dis[maxd];
        b[maxd]=true;
        for(int j=1;j<=n;j++)
        {
            if(!b[j])
             if(a[maxd][j])
              dis[j]=min(dis[j],a[maxd][j]);
        }
    }
     if(ans>=maxn)
      {
          printf("orz");
          return 0;
      }
    printf("%d\n",ans);
    return 0;
}

k算法代码

#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 200001
#define maxn 1234567
using namespace std;
int n,m,x,y,z,ans,tot,fa[N];
struct Edge
{
    int x,y,z;
}edge[N];
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘) f=-1;
        ch=getchar();
    }
    while(ch<=‘9‘&&ch>=‘0‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return f*x;
}
int found(int x)
{
    return fa[x]==x?x:fa[x]=found(fa[x]);
}
int cmp(Edge a,Edge b)
{
    return a.z<b.z;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        edge[i].x=x;
        edge[i].y=y;
        edge[i].z=z;
    }
    sort(edge+1,edge+1+m,cmp);
    for(int i=1;i<=n;i++)
     fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        x=edge[i].x,y=edge[i].y;
        int fx=found(x),fy=found(y);
        if(fx==fy) continue;
        fa[fx]=fy;
        tot++;
        ans+=edge[i].z;
        if(tot==n-1)
         break;
    }
    int fx=found(1);
    for(int i=2;i<=n;i++)
    {
        if(found(i)!=fx)
        {
            printf("orz");
            return 0;
         }
    }
    printf("%d",ans);
    return 0;
}
时间: 2024-12-24 21:46:39

【模板】最小生成树的相关文章

luoguP3366 [模板] 最小生成树

题目链接:https://www.luogu.org/problemnew/show/P3366 思路: 求最小生成树的模板题,求MST有两种算法--Prim.Kruskal. 两者区别:Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣.Prim是以更新过的节点的连边找最小值,Kruskal是直接将边排序. 两者其实都是运用贪心的思路 我使用的Prim算法(邻接表实现),head是表头结点数组,a是表结点数组,len记录未加入生成树的结点到生成树的最小距离,vis用来记录结点是

模板——最小生成树kruskal算法+并查集数据结构

并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每个点只保存祖先,不保存父亲) 最小生成树kruskal:贪心算法+并查集数据结构,根据边的多少决定时间复杂度,适合于稀疏图 核心思想贪心,找到最小权值的边,判断此边连接的两个顶点是否已连接,若没连接则连接,总权值+=此边权值,已连接就舍弃继续向下寻找: 并查集数据结构程序: #include<ios

模板 最小生成树

堆优化的prim算法(跟dijkstra非常的像) #include<iostream> #include<queue> #include<vector> using namespace std; const int inf=99999999; int n,m; vector<pair<int,int> >g[5005];//第一位是距离,第二位使编号 int book[5005],dis[5005]; priority_queue<pai

【模板】图论

一.生成树 洛谷模板最小生成树[跑的还算快的 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 5020 #define M 200008 using namespace std; int n,m,ans; int tot; int fa[N]; struct E{ int x,y,z; }e[M]; bool cmp(E a,E b){ r

【POJ 3241】曼哈顿最小生成树(模板整理)

关于 曼哈顿最小生成树 的证明见:http://www.2cto.com/kf/201505/399861.html 模板: #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct Point{ int x,y,i

最小生成树模板

//最小生成树模板 /* kruskal算法,把所有的边从小到大排序,接下来从小到大考查每条边(u,v); 1.u和v在同一个连通分量中,那么加入(u,v)后会形成环,因此不能选择. 2.如果u和v在不同的联通分量中,那么加入(u,v)一定是最优的. */ #include<iostream> #include<cstring> #include<algorithm> using namespace std; int fat[102];//存放父节点 struct Lu

洛谷P3366 【模板】最小生成树

P3366 [模板]最小生成树 319通过 791提交 题目提供者HansBug 标签 难度普及- 提交  讨论  题解 最新讨论 里面没有要输出orz的测试点 如果你用Prim写了半天都是W- 题目描述有错 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M<=200000) 接下来M行每行包含三个整数Xi.Yi.Zi,表示有一条长度为Zi的无向边连接结点Xi

POJ2560 (最小生成树模板题)

In an episode of the Dick Van Dyke show, little Richie connects the freckles on his Dad's back to form a picture of the Liberty Bell. Alas, one of the freckles turns out to be a scar, so his Ripley's engagement falls through. Consider Dick's back to

HDU 1233 prim kruskal最小生成树模板题

A - 还是畅通工程 Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. Input 测试输入包含若干测试

最小生成树(kruskal模版 Prim模板)

http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2144&cid=1186 最小生成树,最重要的是了解思想 稠密图用Prim,稀疏图用Kruskal K(每次找最小的边连接,一条边连接两个点,所以单路就可以了) 1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 int bin[110]; 5 struct node 6 { 7 int