POJ 2395 Out of Hay

The cows have run out of hay, a horrible event that must be remedied immediately. Bessie intends to visit the other farms to survey their hay situation. There are N (2 <= N <= 2,000) farms (numbered 1..N); Bessie starts at Farm 1. She'll traverse some or all of the M (1 <= M <= 10,000) two-way roads whose length does not exceed 1,000,000,000 that connect the farms. Some farms may be multiply connected with different length roads. All farms are connected one way or another to Farm 1.

Bessie is trying to decide how large a waterskin she will need. She knows that she needs one ounce of water for each unit of length of a road. Since she can get more water at each farm, she's only concerned about the length of the longest road. Of course, she plans her route between farms such that she minimizes the amount of water she must carry.

Help Bessie know the largest amount of water she will ever have to carry: what is the length of longest road she'll have to travel between any two farms, presuming she chooses routes that minimize that number? This means, of course, that she might backtrack over a road in order to minimize the length of the longest road she'll have to traverse.
Input
* Line 1: Two space-separated integers, N and M.

* Lines 2..1+M: Line i+1 contains three space-separated integers, A_i, B_i, and L_i, describing a road from A_i to B_i of length L_i.
Output
* Line 1: A single integer that is the length of the longest road required to be traversed.
Sample Input
3 3
1 2 23
2 3 1000
1 3 43
Sample Output
43
Hint
OUTPUT DETAILS:

In order to reach farm 2, Bessie travels along a road of length 23. To reach farm 3, Bessie travels along a road of length 43. With capacity 43, she can travel along these roads provided that she refills her tank to maximum capacity before she starts down a road.


看到这个题,都想忍不住多多吐槽几句,前几日练了一些这种类型的(最小生成树)题,感觉挺简单的,都是一些模板题,可后来发现,有时候还是不能粗心大意的。这个题主要说的是找出一个最短路中最长的一条路。听得是不是略有些绕口,其实就是让你找出n-1条路,使其总长度最短,输出这些路中,最长的路。   一听是不是觉得用Krusal算法比较简单,是的,我用了两种方法来解决,一个是Krusal,一个是prim算法。这两个都是最小生成树,有些相似,却又有些不相似。

Krusal主要是以边的权值进行从小到大排序的,每次从剩余的边中选择权值比较小的且边的两个顶点不在同一个集合内(不产生回路的边),加到生成树中,直到n-1条边为止。

   Pirm(普利姆)算法和Dijkatra有点相似,Dijkatra使用一个一维数组dis来记录各个顶点到k点的距离,然后每次扫描数组dis,从中选出离远点最近的顶点,然后再通过这个点的所有的边能否更新k到各个顶点的距离(dis[m] > dis[j] + e[j][m]) 则更新 dis[m] = dis[j] + dis[j][m]      Prim 中数组dis 记录“生成树“到各个顶点的距离,也就是记录的最短距离,不是各个顶点到1号顶点的距离,而是每个顶点到任意“树“(已被选入生成树的顶点)的最短距离,即如果 dis[k] > e[j][k]

dis[k] = e[j][k].主要目的是靠近生成树     到最后 不得不多啰嗦几句,当你已经初始化的时候,在输入时,一定要先判断大小,然后再赋值  如 if(t3<e[t1][t2])                    //注意这个判断条件不能省略,因为刚开始的时候,已经将e数组全部附有初值,我就是栽到这的
                e[t1][t2] = e[t2][t1] = t3;

  有的时候  可以用Prim算法比较简单,有的时候用Krusal,一定要知道它们的优缺点,才能够很好的运用

//Kruskal  算法
#include<stdio.h>
#include<algorithm>        //对结构体进行排序的头文件
using namespace std;
int m,n,f[2010];

struct note
{
    int u,v,w;
}e[10010];               //注意数组的大小,不要和n范围给弄混了

int cmp(note a,note b)   //结构体进行从小到大排序
{
    return a.w < b.w;
}

void init()              //并查集初始化
{
    for(int i = 1; i <= n; i++)
        f[i] = i;
}

int getf(int v)         //并查集找祖先的递归函数
{
    if(f[v] == v)
        return v;
    else
    {                                   //路径压缩,在每次返回函数的时候,把它的值改为其祖先
        f[v] = getf(f[v]);
        return f[v];
    }
}

int merge(int v,int u)                 //并查集 合并两 子集合的函数
{
    int t1,t2;
    t1 = getf(v);
    t2 = getf(u);
    if(t1 != t2)                       //判断这两个点是否在同一个集合中
    {
        f[t2] = t1;
        return 1;
    }
    return 0;
}

void Kruskal()
{
    int maxx = -1;
    int num = 0;
    for(int i = 0; i < m; i++)          //从小到大枚举每一条边
    {
        if(merge(e[i].u,e[i].v))        //判断一条边的两个顶点是否已经通过,(判断是否在一个集合中)
        {
            num++;
            if(e[i].w > maxx)           //找出这些路中比较长的路程,存在maxx中
                maxx = e[i].w;
        }
        if(num == n-1)                  //选用n-1条边结束循环
            break;
    }
    printf("%d\n",maxx);
}

int main()
{
    while(~scanf("%d%d",&n,&m))         //n表示的是村庄的数目,  m表示的是道路数
    {
        for(int i = 0; i < m; i++)
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e,e+m,cmp);                //两个村庄的距离进行从近到远排序
        init();                         //并查集初始化
        Kruskal();                      //克鲁斯卡尔
    }
    return 0;
}


//  prim  算法
#include<stdio.h>
#include<string.h>
#define inf 0x3f3f3f3f
int  e[2010][2010],dis[2010],minn;
int m,n,book[2010];
void prim()
{
    memset(book,0,sizeof(book));
    for(int i = 1; i <= n; i++)     //初始化dis数组,这里是1顶点到各个顶点的初始距离
        dis[i] = e[1][i];                   
    book[1] = 1;                    //标记是否生成树
    int num = 1;
    int w;
    int maxx = -1;
    while(num < n)      
    {
        minn = inf;
        for(int i = 1; i <= n; i++)
        {
            if(book[i] == 0 && dis[i] < minn)
            {
                minn = dis[i];
                w = i;
            }
        }
        book[w] = 1;
        if(minn > maxx)                           
            maxx = minn;
        num++;
        for(int k = 1; k <= n; k++)
            if(book[k] == 0 && dis[k] > e[w][k])    //找当前w点所有的边,到k点路程最短,更新生成树到每个非树顶点的距离
                dis[k] = e[w][k];
    }
    printf("%d\n",maxx);
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i = 1; i <= n; i++)             //初始化数据
            for(int j = 1; j <= n; j++)
                if(i == j)
                    e[i][j] = 0;
                else
                    e[i][j] = inf;
        int t1,t2,t3;
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            if(t3<e[t1][t2])                    //注意这个判断条件不能省略,因为刚开始的时候,已经将e数组全部附有初值,我就是栽到这的
                e[t1][t2] = e[t2][t1] = t3;     //由于是无向图,所以需要将反向再储存一遍
        }
        prim();                                 //普里姆算法
    }
    return 0;
}

技术选型 【后端】:Java 【框架】:springboot 【前端】:vue 【JDK版本】:JDK1.8 【服务器】:tomcat7+ 【数据库】:mysql 5.7+ 项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧! 在当今快速发展的信息技术领域,技术选型是决定一个项目成功与否的重要因素之一。基于以下的技术栈,我们为您带来了一份完善且经过实践验证的项目资源,让您在学习和提升编程技能的道路上事半功倍。以下是该项目的技术选型和其组件的详细介绍。 在后端技术方面,我们选择了Java作为编程语言。Java以其稳健性、跨平台性和丰富的库支持,在企业级应用中处于领导地位。项目采用了流行的Spring Boot框架,这个框架以简化Java企业级开发而闻名。Spring Boot提供了简洁的配置方式、内置的嵌入式服务器支持以及强大的生态系统,使开发者能够更高效地构建和部署应用。 前端技术方面,我们使用了Vue.js,这是一个用于构建用户界面的渐进式JavaScript框架。Vue以其易上手、灵活和性能出色而受到开发者的青睐,它的组件化开发思想也有助于提高代码的复用性和可维护性。 项目的编译和运行环境选择了JDK 1.8。尽管Java已经推出了更新的版本,但JDK 1.8依旧是一种成熟且稳定的选择,广泛应用于各类项目中,确保了兼容性和稳定性。 在服务器方面,本项目部署在Tomcat 7+之上。Tomcat是Apache软件基金会下的一个开源Servlet容器,也是应用最为广泛的Java Web服务器之一。其稳定性和可靠的性能表现为Java Web应用提供了坚实的支持。 数据库方面,我们采用了MySQL 5.7+。MySQL是一种高效、可靠且使用广泛的关系型数据库管理系统,5.7版本在性能和功能上都有显著的提升。 值得一提的是,该项目包含了前后台的完整源码,并经过严格调试,确保可以顺利运行。通过项目的学习和实践,您将能更好地掌握从后端到前端的完整开发流程,提升自己的编程技能。欢迎参考博主的详细文章或私信获取更多信息,利用这一宝贵资源来推进您的技术成长之路!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值