1.30学习总结

今天学习的是最小生成树:

生成树:

只要能连通所有顶点而又不产生回路的任何子图都是它的生成树

连接图中所有的点n,并且只有n-1条边的子图就是它的生成树

最小生成树:在生成树中,我们称生成树各边权值和为该树的权。对于无向连通图来说,权值最小的生成树被成为最小生成树。

两种算法:

prim (普里姆算法):

① 先建立一个只有一个结点的树,这个结点可以是原图中任 意的一个结点。

② 使用一条边扩展这个树,要求这条边一个顶点在树中另一 个顶点不在树中,并且这条边的权值要求最小。

③ 重复步骤②直到所有顶点都在树中。

kruskal (克鲁斯卡尔算法)

利用并查集来求最小生成树的算法


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

输入格式
第一行包含两个整数 N,MN,M,表示该图共有 NN 个结点和 MM 条无向边。

接下来 MM 行每行包含三个整数 X_i,Y_i,Z_iX 
i

 ,Y 
i

 ,Z 
i

 ,表示有一条长度为 Z_iZ 
i

  的无向边连接结点 X_i,Y_iX 
i

 ,Y 
i

 。

输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。

输入输出样例
输入 #1复制
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出 #1复制


题解:就是模板题目,考察最小生成树的写法,因为学过了并查集,所以克鲁斯卡尔算法理解的更快,就采用了克鲁斯卡尔算法。

#include
#include
#include
#include
int n,m;
long long int sum;
int f[200005];
struct node
{
    int x;
    int y;
    int z;
} a[200005];
int find(int x)//并查集查找
{
    if(x==f[x])
        return x;
    else
        return find(f[x]);
}
int cmp(const void*a,const void*b)//结构体排序
{
    struct node aa=*(struct node*)a;
    struct node bb=*(struct node*)b;
    return aa.z>bb.z?1:-1;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i1)
        printf("orz\n");
    else
        printf("%lld\n",sum);
    return 0;
}


还记得 NOIP 2011 提高组 Day1 中的铺地毯吗?时光飞逝,光阴荏苒,三年过去了。组织者精心准备的颁奖典礼早已结束,留下的则是被人们踩过的地毯。请你来解决类似于铺地毯的另一个问题。

题目描述
会场上有 n 个关键区域,不同的关键区域由 m 条无向地毯彼此连接。每条地毯可由三个整数 u、v、w 表示,其中 u 和 v 为地毯连接的两个关键区域编号,w 为这条地毯的美丽度。

由于颁奖典礼已经结束,铺过的地毯不得不拆除。为了贯彻勤俭节约的原则,组织者被要求只能保留 K 条地毯,且保留的地毯构成的图中,任意可互相到达的两点间只能有一种方式互相到达。换言之,组织者要求新图中不能有环。现在组织者求助你,想请你帮忙算出这 K 条地毯的美丽度之和最大为多少。

输入格式
第一行包含三个正整数 n、m、K。

接下来 m 行中每行包含三个正整数 u、v、w。

输出格式
只包含一个正整数,表示这 K 条地毯的美丽度之和的最大值。

输入输出样例
输入 #1复制
5 4 3
1 2 10
1 3 9
2 3 7
4 5 3
输出 #1复制
22


题解:

1.表明要将多条红毯铺成一条,即就是合并,所以确定使用克鲁斯卡尔算法。

2.结束条件,红毯只要k条,所以需要一个计数器,当达到所需要的红毯数的时候就需要结束循环

3.题目求最大权值,所以排序要降序

#include 
#include 
int n,m,k;
int cnt=0;
int f[200005];
long long int sum;
struct node
{
    int x;
    int y;
    int z;
} a[200005];
int find(int x)//并查集查找
{
    if(x==f[x])
        return x;
    else
        return find(f[x]);
}
int cmp(const void*a,const void*b)
{
    struct node aa=*(struct node*)a;
    struct node bb=*(struct node*)b;
    return aa.z>bb.z?-1:1;//降序
}
int main()
{

    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=n; i++)//初始化
        f[i]=i;
    for(int i=1; i<=m; i++)
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    qsort(a+1,m,sizeof(a[1]),cmp);//降序排序
    for(int i=1; i<=m; i++)
    {
        int x=find(a[i].x);
        int y=find(a[i].y);
        if(x==y)
            continue;
        sum+=a[i].z;//权值相加
        f[y]=x;
        cnt++;
        if(cnt==k)//合并的红毯数已经达到题目给出的红毯数
            break;
    }
    printf("%lld\n",sum);
    return 0;
}

你可能感兴趣的:(学习)