咱們枚舉每一條邊的流量x,將它做爲底流(也就是比它大的的流量變成差值,比它小的流量爲0),而後咱們設x就是路徑上第K大的那個邊的流量。而後跑最短路,加上dis[n]就是當前的答案。而後取min便可。 算法時間複雜度$O(n^2logn)$ 爲何這樣子就是最小的呢?????我也很懵逼啊 由於你考慮ans_x是第K大的流量,設當前處理的爲x。 若是按照上述規定來跑最短路,顯然上述所求最短路加上K*ans_x就是答案,並且這個最短路徑是必定肯定的。下面咱們就要求ans_x——若是咱們進行遍歷而後取min的話,若是保證x!=ans_x的時候不優呢? 若是x比ans_x小,那麼「還有流量」的邊必定大於等於K。這樣的話最後統計答案最短路會長,x變小——可是變化幅度沒有前面的大,因此不優。 若是x比ans_x大,那麼「還有流量」的邊必定小於等於K。這樣的話最後統計答案最短路會短,x變大——可是變化幅度比前面的大,因此不優。ios
代碼以下:算法
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #define MAXN 5010 using namespace std; int n,m,t,k; int head[MAXN],done[MAXN]; long long ans=(long long)1e15; long long dis[MAXN]; vector<int>vec; struct Edge{int nxt,to,dis;}edge[MAXN<<1]; struct Node { int u; long long w; friend bool operator < (struct Node x,struct Node y) {return x.w>y.w;} }; inline void add(int from,int to,int dis) { edge[++t].nxt=head[from]; edge[t].to=to; edge[t].dis=dis; head[from]=t; } inline long long dij(int x) { priority_queue<Node>q; for(int i=0;i<=n;i++) dis[i]=(long long)1e15,done[i]=0; q.push((Node){1,0}); dis[1]=0; while(!q.empty()) { int u=q.top().u; q.pop(); if(done[u]) continue; done[u]=1; for(int i=head[u];i;i=edge[i].nxt) { int v=edge[i].to; long long w=max(edge[i].dis-x,0); //printf("v=%d w=%lld %lld\n",v,w,edge[i].dis); if(dis[u]+w<dis[v]) dis[v]=dis[u]+w,q.push((Node){v,dis[v]}); } } return dis[n]; } int main() { //freopen("skd.in","r",stdin); //freopen("skd.out","w",stdout); freopen("ce.in","r",stdin); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w),add(v,u,w); vec.push_back(w); } ans=dij(0); printf("%lld\n",ans); for(int i=0;i<vec.size();i++) ans=min(ans,1ll*vec[i]*k+dij(vec[i])),printf("%lld\n",ans); printf("%lld\n",ans); return 0; }