拆点,每个点拆成用了ki次免费航线,然后跑一遍Spfa就好了。
不过裸Spfa可能会超时(反正我的跑了6000多MS),还是用Dijkstra的好。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int inf=1e9; struct Edge{int to,next,v;}e[100005]; int head[10005],d[10005][15],cnt,n,m,k; bool inq[10005][15]; void ins(int u,int v,int w){ cnt++;e[cnt].to=v; e[cnt].next=head[u];head[u]=cnt; e[cnt].v=w; } void spfa(int s){ memset(d,0x3f,sizeof(d)); d[s][0]=0;queue<int>q,t;q.push(s);t.push(0); while(!q.empty()){ int u=q.front(),ti=t.front();q.pop();t.pop(); inq[u][ti]=false; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(d[v][ti]>d[u][ti]+e[i].v){ d[v][ti]=d[u][ti]+e[i].v; if(!inq[v][ti]){inq[v][ti]=true;q.push(v);t.push(ti);} } if(ti<k&&d[v][ti+1]>d[u][ti]){ d[v][ti+1]=d[u][ti]; if(!inq[v][ti+1]){inq[v][ti+1]=true;q.push(v);t.push(ti+1);} } } } } int main(){ scanf("%d%d%d",&n,&m,&k); int s,t;scanf("%d%d",&s,&t); int a,b,c; while(m--){ scanf("%d%d%d",&a,&b,&c); ins(a,b,c);ins(b,a,c); } spfa(s); int ans=inf; for(int i=0;i<=k;i++) ans=min(ans,d[t][i]); printf("%d",ans); return 0; }