https://vjudge.net/contest/350975#problem/E
题意:给一张无向图,求一条从1到n路上的最大边,使得其最小,同时还要满足 这条路长度<=最短路*(1+X%)
先跑一边最短路,求出最短路
然后二分答案,求在最大边为mid的情况下的最短路(在松弛的时候判断一下边大于mid就不松弛),用spfa T了,
得用队列优化dij
#include<bits/stdc++.h>
using namespace std;
const long long maxn = 100009;
typedef pair<long long,long long > pii;
struct node
{
long long to,next;
double w;
} edge[maxn<<1];
double per,minn,tot;
long long ans;
long long head[maxn<<1],flag[maxn],n,cnt,dis[maxn];
void add(long long u,long long v,double w)
{
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
long long dij(long long s,long long t,long long lim)
{
memset(dis,0x3f3f3f3f,sizeof(dis));
priority_queue<pii,vector<pii>,greater<pii> > que;
dis[s] = 0;
que.push(make_pair(0,s));
while(!que.empty())
{
pii p =que.top();
que.pop();
if(dis[p.second]<p.first)
{
continue;
}
for(long long i = head[p.second]; i != -1; i = edge[i].next)
{
long long to = edge[i].to;
if(dis[to]>dis[p.second]+edge[i].w&&edge[i].w<=lim)
{
dis[to] = dis[p.second]+edge[i].w;
que.push(make_pair(dis[to],to));
}
}
}
return dis[t];
}
int main()
{
long long i,j,m,a,b,c,l,r,num,ans;
memset(head,-1,sizeof(head));
scanf("%lld %lld %lf",&n,&m,&per);
per = 1.0+per/100.0;
for(i = 0; i < m; i++)
{
scanf("%lld %lld %lld",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
minn = dij(1,n,0x3f3f3f3f);
l = 0;
r = 1e14;
ans = 0x3f3f3f3f;
while(l<=r)
{
long long mid = (l+r)/2;
num = dij(1,n,mid);
if(num*1.0<= minn*per)
{
r = mid-1;
ans = min(ans,mid);
}
else
l = mid+1;
}
printf("%lld\n",ans);
return 0;
}
来源:CSDN
作者:.帅帅.
链接:https://blog.csdn.net/qq_31617881/article/details/103933260