截图留念
题目大意:求图中一条1到n的路径,要求第(k+1)大的边权值最小.
题解:二分答案后题目转化为求图中是否有一条1到n的路径满足权值比mid大的边的个数不大于k,然后我们把大于mid的边权赋为1,其他边边权赋为0,跑最短路即可.
不加优化的SPFA慢成狗…
AC code:
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int N=1010;
const int M=10010;
const int INF=1<<29;
int n,m,k;
int w[M],dist[N];
int G[N][N],tG[N][N];
void SPFA(int val){
queue<int> Q;
Q.push(1);
for(int i=2;i<=n;i++) dist[i]=INF;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
tG[i][j]=G[i][j]>val;
while(!Q.empty()){
int x=Q.front();
Q.pop();
for(int i=1;i<=n;i++){
if(G[x][i]&&dist[x]+tG[x][i]<dist[i]){
dist[i]=dist[x]+tG[x][i];
Q.push(i);
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d%d",&u,&v,&w[i]);
G[u][v]=G[v][u]=w[i];
}
sort(w+1,w+m+1);
SPFA(0);
if(dist[n]<=k){
printf("0\n");
return 0;
}
else if(dist[n]==INF){
printf("-1\n");
return 0;
}
int L=0,R=m+1;
while(L+1!=R){
int mid=(L+R)>>1;
SPFA(w[mid]);
if(dist[n]<=k) R=mid;
else L=mid;
}
printf("%d\n",w[R]);
return 0;
}