迪杰斯特拉和克鲁斯卡尔的合并

题意分析

1.任务

给出若干个木条的长度,求出不能围成的最大长度

有长度是一的都能围成

2.读入

n,m表示木条的种类和能切的长度

注意:x-d必须≥1

3.输出

无解(1.不存在,2.无限大)输出-1

有解输出

数据范围

1

算法分析

1.模拟

连续a[i]中的最小值

最短路

迪杰斯特拉算法

1.基本算法

Dijkstra算法是典型的 算法。 Dijkstra算法是很有代表性的 算法。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用 OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。

2.权变的解释

按照这种算法来说,做这个程序应该是不难的,但有的时候会超时

这种算法支持多方位控制

注意啦!千万做这道题的时候不要尝试用prim做
以下可以帮助你理解

实现

    1. 将与源点相连的点加入 堆,并调整堆。
    1. 选出堆顶元素u(即代价最小的元素),从堆中删除,并对堆进行调整。
    1. 处理与u相邻的,未被访问过的,满足三角不等式的顶点
  • 1):若该点在堆里,更新距离,并调整该元素在堆中的位置。
  • 2):若该点不在堆里,加入堆,更新堆。
    1. 若取到的u为终点,结束算法;否则重复步骤2、3。

2.实现合并

做完的结果

看不到的点这:https://i.imgur.com/FDVYIxm.png

我们开始实现克里斯卡尔和迪杰斯特拉的合并啦!

我们首先要知道,这两个的算法其实是同一个思想的

    ++num;
    data[num].x=x;
    data[num].y=y;
    data[num].z=z;
    data[num].next=h[x];
    h[x]=num;
    ++num;
    data[num].x=y;
    data[num].y=x;
    data[num].z=z;
    data[num].next=h[y];
    h[y]=num;

这个,就是合并成功啦,我们需要在前面读入一些

    scanf("%d%d",&t,&n);    
    num=0;

还有就是

memset(flag,false,sizeof flag);
flag[v]=true;
    for(int j=h[v];j!=-1;j=data[j].next){
        x=data[j].x; y=data[j].y; z=data[j].z;
        if(!flag[y] and z+f[v]<f[y]){
            f[y]=z+f[v];
        }
    }

3.读入什么

读入一个相对应的点

相对应点我点的强度为:父节点+权的强度=最后强度

结论克鲁斯卡尔的定义确实类似于迪杰斯特拉

最后附上程序


#include<cstdio>
#include<cstring>
struct node{
    int x,y,z,next;
};
const int N1=1100;
const int N2=2200;
const int INF=0x7FFFFFFF;
bool flag[N1];
node data[N2*2];
int f[N1], h[N1];
int t,n,num,x,y,z,v;
int main(){
    scanf("%d%d",&t,&n);    
    num=0;
    memset(h,-1,sizeof h);
    for(int i=1;i<=t;++i){
        scanf("%d%d%d",&x,&y,&z);
        ++num;
        data[num].x=x;
        data[num].y=y;
        data[num].z=z;
        data[num].next=h[x];
        h[x]=num;
        ++num;
        data[num].x=y;
        data[num].y=x;
        data[num].z=z;
        data[num].next=h[y];
        h[y]=num;
    }
    memset(flag,false,sizeof flag);
    for(int i=0;i<=n;++i)f[i]=INF;
    f[1]=0;
    for(int i=1;i<=n-1;++i){
        v=0;

        for(int j=1;j<=n;++j)if(!flag[j] and f[j]<f[v])
            v=j;

        flag[v]=true;
        for(int j=h[v];j!=-1;j=data[j].next){
            x=data[j].x; y=data[j].y; z=data[j].z;
            if(!flag[y] and z+f[v]<f[y]){
                f[y]=z+f[v];
            }
        }
    }
    printf("%d",f[n]);

    return 0;
}

好啦,今天就到这里啦,下期再见!

Goodbye!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值