求从1到n的路径在免费K条路径下剩余的路径中最小的最大值。
二分搜索+SPFA
每次枚举边len,假设最大的边为len,将小于len的边的长度设为0,大于len的边的长度设为1,求1到n的最短路径,若最短路径<=k,则len是满足题意的,可以枚举比len更小的值,否则最小最大边一定比当前的len大
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int INF=1000000000;
int n,p,k;
int maxLength;
int map[2005][2005];
int ans;
bool tu(int len)
{
queue<int> Q1;
Q1.push(1);
int visit[2005],i;
memset(visit,0,sizeof(visit));
visit[1]=1;
int dis[2005];
for(i=1;i<=n;i++) dis[i]=INF;
dis[1]=0;
while(!Q1.empty())
{
int u=Q1.front();
Q1.pop();
visit[u]=0;
for(i=1;i<=n;i++) if(map[u][i]<INF)
{
int cc=map[u][i]>len?1:0;
if(dis[u]+cc<dis[i])
{
dis[i]=dis[u]+cc;
if(!visit[i]) visit[i]=1,Q1.push(i);
}
}
}
return dis[n]<=k;
}
void solve(int s,int e)
{
int mid;
ans=-1;
while(s<=e)
{
mid=(s+e)>>1;
if(tu(mid)) e=mid-1;
else s=mid+1;
}
if(tu(e)) ans=e;
else if(tu(s)) ans=s;
else ans=-1;
}
int main()
{
while(scanf("%d %d %d",&n,&p,&k)!=EOF)
{
int u,v,w;
int i,j;
for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=INF;
maxLength=-1;
for(i = 1;i<=p;i++)
{
scanf("%d %d %d",&u,&v,&w);
map[u][v] = map[v][u] = w;
if(maxLength < w)
{
maxLength = w;
}
}
solve(1,maxLength);
printf("%d\n",ans);
}
return 0;
}