分析

本题主要就是一个转化
当我们看到数据范围,就可以大胆猜测较高复杂度的算法
因为维护最大值比较麻烦
我们考虑用二分答案限制最大值
然后就可以顺理成章的想出
的路径长度标为1
跑一个最短路
如果最后的Dist[T]那么这就是一个可行的解
以此二分即可求得答案

代码

//P1948
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>

#define LL long long
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(int i=A;i<=B;i++)
#define BOR(i,A,B) for(int i=A;i>=B;i--)
#define INF 0x3f3f3f3f
using namespace std;
const int MaxN=2e4+10;

int Next[MaxN<<1],Head[MaxN],End[MaxN<<1],Cur,Val[MaxN<<1];
int Total,Side,Limit,cnt,h[1005],Dist[1005],Mine[1005];
bool Jud[1005];

inline void Add_Edge(int u,int v,int w) {
    Next[++Cur]=Head[u];
    Head[u]=Cur;
    End[Cur]=v;
    Val[Cur]=w;
}

inline bool check(int x) {
    Cl(Dist,0x3f);
    int R=0,L=1,i,New,s;
    Dist[1]=0;
    Mine[R]=1;
    Jud[1]=1;
    while(R!=L) {
        New=Mine[R];R++;
        if(R==1001)R=0;
        i=h[New];
        for(int i=Head[New];i;i=Next[i]) {
            if(Val[i]>x) s=Dist[New]+1;
            else s=Dist[New];
            if(s<Dist[End[i]]) {
                Dist[End[i]]=s;
                if(!Jud[End[i]]) {
                    Mine[L++]=End[i];
                    Jud[End[i]]=1;
                    if(L==1001)L=0;
                }
            }
        }
        Jud[New]=0; 
    }
    if(Dist[Total]<=Limit)return 1;
    return 0;
 }
int main() {
    scanf("%d %d %d",&Total,&Side,&Limit);
    int u,v,L,l=0,r=1000000,mid;
    FOR(i,1,Side) {
        scanf("%d %d %d",&u,&v,&L);
        Add_Edge(u,v,L);
        Add_Edge(v,u,L);
    }
    int Ans=-1;
    while(l<=r) {
        mid=(l+r)>>1;
        if(check(mid)){r=mid-1;Ans=mid;}
        else l=mid+1;
    }
    printf("%d\n",Ans);
    system("pause");
    return 0;
}