EZOJ #375高速公路
作者:互联网
分析
我们可以先跑一遍全价的最短路
之后我们枚举这个第k大的价格w[i]
将其它边减这个边的权值和0取max
在跑出最短路之后加上减去的费用,即w[i]*k
我们发现如果价值大于w[i]的边小于k个
那么由于小于w[i]的边经过之前操作后权值会比原先大所以一定不有
所以我们不难得出一定是这个点正好是第k大时才是最优的
最终所有答案取min即可
代码
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define int long long const int inf = 1e15+7; int n,m,k,s,t,d[3010],vis[3010],wh,f[3010]; priority_queue<pair<int,int> >q; vector<pair<int,int> >v[3010]; inline int dij(){ int i,j,k; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++)d[i]=inf; d[s]=0; q.push(mp(0,s)); while(!q.empty()){ int x=q.top().se; q.pop(); if(vis[x])continue; vis[x]=1; for(i=0;i<v[x].size();i++){ int y=v[x][i].fi,z=max(0ll,v[x][i].se-wh); if(d[y]>d[x]+z){ d[y]=d[x]+z; q.push(mp(-d[y],y)); } } } return d[t]; } signed main(){ int i,j; scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&s,&t); for(i=1;i<=m;i++){ int x,y,z; scanf("%lld%lld%lld",&x,&y,&z); v[x].pb(mp(y,z)); f[i]=z; } int ans=dij(); for(i=1;i<=m;i++){ wh=f[i]; ans=min(ans,dij()+k*wh); } cout<<ans; return 0; }
标签:int,3010,long,高速公路,vis,lld%,375,EZOJ,define 来源: https://www.cnblogs.com/yzxverygood/p/11520454.html