题目连接
http://codeforces.com/gym/101490
题目大意
你有一张图,每两点之间有一定距离,计算出比最短路大x%之内的路径中最长边的最小值
分析
先跑一遍最短路,然后二分答案枚举最长边长度mid。在重新构图过程中去掉所有大于mid的边,看这样跑出的最短路是否满足要求(小于等于最短路*(100+x)/100即可)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const long long inf=1e18+9;
long long x[5000100],y[5000100],z[5000100];
vector<pair<long long,long long> >v[5000100];
priority_queue<pair<long long,long long> >Q;
long long n,m,k,ruler;
long long length[5000100];
bool is[5000100];
bool go(long long mid)
{ long long i,j,p,q;
for(i=1;i<=n;i++)
v[i].clear(),
length[i]=inf;
memset(is,0,sizeof(is));
for(i=1;i<=m;i++)
if(z[i]<=mid){
v[x[i]].push_back(make_pair(y[i],z[i]));
v[y[i]].push_back(make_pair(x[i],z[i]));
}
length[1]=0;
Q.push(make_pair(0,1));
while(!Q.empty()){
long long a,b,c;
a=Q.top().second;
Q.pop();
if(is[a])continue;
is[a]=1;
for(i=0;i<v[a].size();i++){
b=v[a][i].first;
c=v[a][i].second;
if(length[b]>length[a]+c){
length[b]=length[a]+c;
Q.push(make_pair(-length[b],b));
}
}
}
if(length[n]>=inf)return false;
if(length[n]*100<=ruler*(100+k))
return true;
return false;
}
int main()
{ long long i,j,mid=-1,ri,le;
cin>>n>>m>>k;
for(i=1;i<=m;i++)
cin>>x[i]>>y[i]>>z[i];
ri=1e9+7;
le=0;
go(1e9+7);
ruler=length[n];
while((le+ri)>>1!=mid){
mid=(le+ri)>>1;
//cout<<mid<<endl;
if(go(mid))ri=mid;
else le=mid;
}
cout<<ri<<endl;
return 0;
}