BZOJ 2763 飞行路线(分层图最短路)题解
题意:中文题意不解释...
思路:分层图最短路,我们再开一维用来表示当前用了多少次免费次数,dis[i][j]就表示到达i点用了j次免费的最短路,有点DP的感觉。
当个模板用
参考:分层图最短路
代码:
#include<cstdio> #include<set> #include<cmath> #include<queue> #include<vector> #include<cstring> #include<algorithm> #include<iostream> #define ll long long using namespace std; const int maxn = 10000+5; const int INF = 0x3f3f3f3f; int dis[maxn][15]; //走到i已经免费j次最短路 int vis[maxn][15]; int n,m,k; struct node{ int to,val; node(int _t = 0,int _v = 0):to(_t),val(_v){} }; vector<node> G[maxn]; void spfa(int st){ memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int> q; while(!q.empty()) q.pop(); vis[st][0] = 1; dis[st][0] = 0; q.push(st),q.push(0); //点和当前使用免费次数 while(!q.empty()){ int u = q.front();q.pop(); int j = q.front();q.pop(); //j是用了几次免费 for(int i = 0;i < G[u].size();i++){ int v = G[u][i].to; if(dis[u][j] + G[u][i].val < dis[v][j]){ //假如不免费 dis[v][j] = dis[u][j] + G[u][i].val; if(!vis[v][j]){ vis[v][j] = 1; q.push(v),q.push(j); } } if(j < k && dis[u][j] < dis[v][j + 1]){ //免费 dis[v][j + 1] = dis[u][j]; if(!vis[v][j + 1]){ vis[v][j + 1] = 1; q.push(v),q.push(j + 1); } } } vis[u][j] = 0; } } int main(){ while(scanf("%d%d%d",&n,&m,&k) != EOF){ for(int i = 0;i <= n;i++) G[i].clear(); int s,t; scanf("%d%d",&s,&t); ++s,++t; for(int i = 0;i < m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); ++u,++v; G[u].push_back(node(v,w)); G[v].push_back(node(u,w)); } spfa(s); int ans = INF; for(int i = 0;i <= k;i++){ ans = min(ans,dis[t][i]); } printf("%d\n",ans); } return 0; }