题目
题目大致意思是给一张无向图,每条边有边权,有k条边可以把边权设为0,求一条路径使
路径上的最大的边权最小。
一般情况下最大值最小或最小值最大可以用二分去解,此题不例外。
我们二分答案x把边权大于x的边边权设为1,跑SPFA,求出最短路,比较k与最短路径如果
k>distance_min 那么答案可以更小,否则,答案必须变大。
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=1001;
const int INF=2147483647;
struct Edge{
int from,to,dist,flag;
};
vector<Edge> edges;
vector<int> G[MAXN];
void Addedge(int f,int t,int d){
edges.push_back((Edge){f,t,d});
int m=edges.size();
G[f].push_back(m-1);
}
int d[MAXN];
bool inq[MAXN];
int m,n;
int k;
bool SPFA(int x){
for(int i=0;i<edges.size();i++) edges[i].flag=edges[i].dist>x;
memset(inq,false,sizeof(inq));
queue<int> q;
for(int i=2;i<=n;i++) d[i]=INF;
q.push(1);
inq[1]=true;
while(!q.empty()){
int u=q.front();q.pop();
inq[u]=false;
for(int i=0;i<G[u].size();i++){
Edge &e=edges[G[u][i]];
if(d[e.to]>d[u]+e.flag){
d[e.to]=d[u]+e.flag;
if(!inq[e.to]) q.push(e.to),inq[e.to]=true;
}
}
}
return d[n]<=k;
}
void init(){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<m;i++){
int f,t,d;
scanf("%d%d%d",&f,&t,&d);
Addedge(f,t,d);
Addedge(t,f,d);
}
}
int main(){
freopen("phoneline.in","r",stdin);
freopen("phoneline.out","w",stdout);
init();
SPFA(0);
if(d[n]==INF){
printf("-1\n");
return 0;
}
int L=0,R=1000000;
while(L<R){
int mid=(L+R)>>1;
if(SPFA(mid)) R=mid;
else L=mid+1;
}
printf("%d\n",L);
#ifdef DEBUG
while(1);
#endif
return 0;
}