对于二分出的答案x而言,验证答案等价于将所有边权>x的边赋成1,否则赋成0,然后判断从1到n的最短路是否<=K。
#include<cstdio> #include<cstring> #include<queue> using namespace std; #define N 1001 #define M 10001 int n,m,K,Xs[M],Ys[M],Zs[M]; int first[N],next[M<<1],v[M<<1],en; bool w[M<<1]; void AddEdge(int U,int V,bool W) { v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en; } queue<int>q; bool inq[N]; int d[N]; void spfa() { memset(d,0x7f,sizeof(int)*(n+1)); d[1]=0; q.push(1); inq[1]=1; while(!q.empty()) { int U=q.front(); for(int i=first[U];i;i=next[i]) if(d[v[i]]>d[U]+w[i]) { d[v[i]]=d[U]+w[i]; if(!inq[v[i]]) {q.push(v[i]); inq[v[i]]=1;} } q.pop(); inq[U]=0; } } bool check(int x) { en=0; memset(first,0,sizeof(int)*(n+1)); for(int i=1;i<=m;++i) {AddEdge(Xs[i],Ys[i],Zs[i]>x); AddEdge(Ys[i],Xs[i],Zs[i]>x);} spfa(); return d[n]<=K; } int main() { scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=m;++i) scanf("%d%d%d",&Xs[i],&Ys[i],&Zs[i]); int l=0,r=1000001; while(r>l) { int mid=(l+r>>1); if(check(mid)) r=mid; else l=mid+1; } printf("%d ",l<=1000000?l:(-1)); return 0; }