二分答案spfa。设>=mid的边为1,<mid的边为0,就可以求出需要免费的道路有多少条。判断一下即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 1050 #define maxe 20050 #define inf 0x7f7f7f7f using namespace std; struct edge { int v,w,nxt,flag; }e[maxe]; int n,m,k,a,b,c,nume=0,g[maxv],minn=inf,maxn=0,ans=inf,prev[maxv],pree[maxv],dis[maxv]; queue <int> q; bool vis[maxv]; void addedge(int u,int v,int w) { e[++nume].v=v; e[nume].nxt=g[u]; e[nume].w=w; g[u]=nume; } void lable(int mid) { for (int i=1;i<=nume;i++) { if (e[i].w<=mid) e[i].flag=0; else e[i].flag=1; } } int spfa() { while (!q.empty()) q.pop(); memset(vis,false,sizeof(vis)); memset(prev,0,sizeof(prev)); memset(pree,0,sizeof(pree)); fill(dis+1,dis+n+1,inf); q.push(1);dis[1]=0;vis[1]=true; while (!q.empty()) { int head=q.front(); q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if (dis[v]>dis[head]+e[i].flag) { dis[v]=dis[head]+e[i].flag; prev[v]=head;pree[v]=i; if (!vis[v]) { vis[v]=true; q.push(v); } } } vis[head]=false; } return dis[n]; } void find() { int left=minn,right=maxn; while (left<=right) { int mid=(left+right)>>1; lable(mid); int regis1=spfa(),regis2=0,regis3=0; if (regis1>k) left=mid+1; else { int now=n; while (now!=1) { if (e[pree[now]].flag==0) regis2=max(regis2,e[pree[now]].w); now=prev[now]; } ans=min(ans,regis2); right=mid-1; } } } int main() { scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); minn=min(minn,c);maxn=max(maxn,c); addedge(a,b,c); addedge(b,a,c); } find(); if (ans!=inf) printf("%d\n",ans); else printf("-1\n"); return 0; }