浏览器标题切换
浏览器标题切换end

HDU1595 - find the longest of the shortest - Dijkstra+记录路径

题意

给出的所有路中存在一条路正在修建,

问要从1走到n,找出最短路径的最大长度

思路

  1. 先一遍dijkstra找到最短路径长度,并且记录路径

  2. 再逐个删掉通向最短路径的每一条边换成别的能够到达终点的路

  3. 计算其最大长度

  • 给定时间是5s,不会超时

  • 难点:在记录路径上

AC代码

#include<iostream>
#include<string.h>
#include<cmath>
#include<iomanip>
#define inf 0x3f3f3f3f
#define ios() std::ios::sync_with_stdio(false)
#define cin() cin.tie(0)
#define cout() cout.tie(0)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;

int vertex[1001];//记录首先求得的最短路径所经过的顶点
int n,m;//n顶点总个数,m是边数
int e[1001][1001];
int dis[1001],dis1[1001],dis2[1001];
int book[1001];
int flag;

void init()
{
    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  dijkstra(int *dis)
{
    mem(book);mem(dis1);mem(dis2);
    for(int i=1;i<=n;i++)
        dis[i]=e[1][i];
    book[1]=1;
    int u;
    for(int i=2;i<=n;i++)
    {
        int minn=inf;
        for(int j=1;j<=n;j++)
        {
            if(book[j]==0&&dis[j]<minn)
            {
                u=j;
                minn=dis[j];
            }
        }
        book[u]=1;
        for(int k=1;k<=n;k++)
        {
            if(e[u][k]<inf&&dis[u]+e[u][k]<dis[k])
            {
                dis[k]=dis[u]+e[u][k];
                if(flag)//如果flag=1,则开始记录最短路的路径
                {
                    vertex[k]=u;//记录顶点
                }
            }
        }
    }
    return dis[n];
}

int main()
{
    ios();cin();cout();
    int x,y,z;
    while(cin>>n>>m)
    {
        mem(dis);mem(vertex);mem(e);
        init();
        for(int i=0; i<m; i++)
        {
            cin>>x>>y>>z;
            e[x][y]=z;
            e[y][x]=z;
        }

        flag=1;mem(dis1);
        fill(vertex,vertex+1001,1);
        int shortest=dijkstra(dis1);
      //  cout<<shortest<<"**"<<endl;

//        for(int i=n;i>=2;i--)
//            cout<<vertex[i]<<" ";

        flag=0;//通过控制flag决定是否记录路径
        int w=n;//一步步倒回去替换掉每一段的距离且变成无穷大,寻找其他边
        int ans=shortest;
        while(w!=1)//   通过while去控制是否已经倒退回去遍历到所有的边
        {
          //  cout<<"***"<<endl;
            int frontt=vertex[w];
            int ori=e[frontt][w];
            e[frontt][w]=e[w][frontt]=inf;//第一次进去先变最后一条边
            mem(dis2);
            int ww=dijkstra(dis2);
          //  if(ww!=inf)
                ans=max(ww,ans);
            e[frontt][w]=e[w][frontt]=ori;
            w=frontt;
           // 变成无穷大之后再进行下一次找的时候可能会需要到这条边,所以需要恢复
        }
        cout<<ans<<endl;
    }
    return 0;
}
posted @   抓水母的派大星  阅读(225)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示