最短路:求最長最短路

tannnnnnnone發表於2020-11-05

列舉刪邊跑Dijskra


HDU - 1595 find the longest of the shortest

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <bitset>
#include <vector>
#include<cstring>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline int read(){int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
const int maxn = 1e3+5;
int n,m;
int dis[maxn],pre[maxn],par[maxn];
int E[maxn][maxn];
bool vis[maxn],flag=false;
void Dijskra(int s)
{
    memset(dis,INF,sizeof(dis));
    memset(par,-1,sizeof(par));  // par 記錄路徑
    memset(vis,false,sizeof(vis));
    dis[s]=0;
    for(int i=1;i<n;i++)
    {
        int node=-1;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&(node==-1||dis[node]>dis[j]))
                node=j;
        for(int j=1;j<=n;j++){
            if(dis[j]>dis[node]+E[node][j])
                dis[j]=dis[node]+E[node][j],par[j]=node;
        }
        vis[node]=true;
    }
    if(!flag){
        for(int i=1;i<=n;i++) pre[i]=par[i];
        flag=true;
    }
}
/* 題意:求最長最短路
 * 分析:列舉每一邊進行刪減,每次再跑Dijskra ,再取Max即可
 */
int main()
{
    while (~scanf("%d%d",&n,&m))
    {
        memset(E,INF,sizeof(E));
        for(int i=1;i<=m;i++)
        {
            int u=read(),v=read(),w=read();
            E[u][v]=min(w,E[u][v]);
            E[v][u]=E[u][v];
        }

        int ans=-INF,q=n;
        flag=false;
        Dijskra(1);
        if(dis[n]!=INF) ans=max(dis[n],ans);
        while (pre[q]!=-1) // pre儲存的是最短路每一條邊,相當於路徑回溯過程
        {
            int p=pre[q],w=E[p][q];
            E[p][q]=INF,E[q][p]=INF;
            Dijskra(1);
            if(dis[n]!=INF) ans=max(dis[n],ans);
            E[p][q]=w,E[q][p]=w;
            q=p;
        }
         printf("%d\n",ans);
    }
    return 0;
}

相關文章