边没有负权,最短路最多只有n条边
很暴力的思想:
先跑一遍最短路,找出最短路上的边,枚举每条边,翻倍,放进原图再跑一遍。取最大值
好熟悉啊
分层建图,建k层
每层内部是原图
若原图中u到v有连边,则由本层的u向下一层的v连一条边权为0的单向边
当然对于某些duliu的图(比如边数<k),用不完k次机会,所以我们还要在本层的u向下一层的u连一条边权为0的边
跑第一层的1到第k层的N的最短路
可能是唯一的代码:
#include<bits/stdc++.h> #define ll long long using namespace std; inline int read() { char ch=getchar(); int x=0;bool f=0; while(ch<'0'||ch>'9') { if(ch=='-')f=1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); } return f?-x:x; } int n,m,k,head[2000009],cnt; struct Ed { int to,dis,nxt; }edge[20000009]; void add(int fr,int to,int dis) { cnt++; edge[cnt].to=to; edge[cnt].dis=dis; edge[cnt].nxt=head[fr]; head[fr]=cnt; } int dis[2000009]; priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q; bool vis[2000009]; void dij() { q.push(make_pair(0,1)); memset(dis,0x3f,sizeof(dis)); dis[1]=0; while(!q.empty()) { int now=q.top().second; q.pop(); if(vis[now])continue; vis[now]=1; for(int e=head[now];e;e=edge[e].nxt) { if(dis[now]+edge[e].dis<dis[edge[e].to]) { dis[edge[e].to]=dis[now]+edge[e].dis; q.push(make_pair(dis[edge[e].to],edge[e].to)); } } } } int main() { n=read(),m=read(),k=read(); for(int i=1;i<=m;i++) { int fr=read(),to=read(),dis=read(); for(int j=1;j<=k+1;j++) { add((j-1)*n+fr,(j-1)*n+to,dis); add((j-1)*n+to,(j-1)*n+fr,dis); add((j-1)*n+fr,j*n+to,0); add((j-1)*n+to,j*n+fr,0); } } int ans=214748364; dij(); for(int i=1;i<=k+1;i++) ans=min(ans,dis[n*i]); printf("%d",ans); }