https://nanti.jisuanke.com/t/31001
分层图最短路 模板题
分层图最短路一般就是能够进行一定次数的操作让图中的某些边的边权变为0或者减半之类的,这些操作不是预先给出的是需要我们自己选择一些边。
这种情况下我们用普通最短路是没有办法的,所以需要用到分层图思想。
所谓分层图,就是状态是多维的一个巨大的图,正常的最短路我们是在一个二维的图中进行的,而用到分层图的时候就需要在多维空间内进行。
通常情况下须要用到分层图思想的题目都有一些干扰操作(常见的就是能够将边权降低什么的)(P.S.前提是这些操作的数目不太大)。我们对这些干扰操作的解决方法就是把原图“复制”,并且一般来说干扰操作有多少次就要复制多少。
每一层图都是由唯一的原图复制来的。因此这些不同层次的图就具有一些同样的性质。因此非常多时候所谓的复制事实上仅仅需要我们在逻辑上把图当成非常多层图来处理,分析出层的概念。根本不需要在程序里进行新图的存储。
并且这些不同层次的图有类似的性质。大部分时候我们的计算结果是类似或者同样的,因此仅仅要计算一次。存储结果,而不须要重复计算。因此不会导致问题的规模变大。
层之间是拓扑有序的。
#include
using namespace std;
const long long INF=10000000000000000LL;
const int MAXN=100010;
int K;
struct qnode{
int v;
int tt;
long long c;
qnode(int _v=0, int _tt = 0,int _c=0):v(_v),tt(_tt),c(_c){}
bool operator <(const qnode &r)const{
return c>r.c;
}
};
struct Edge{
int v,cost;
Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vectorE[MAXN];
bool vis[MAXN][11];
long long dist[MAXN][11];
void Dijkstra(int n,int start){
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++) {
for (int k = 0; k <= K; k++)
dist[i][k] = INF;
}
priority_queueque;
while(!que.empty())que.pop();
dist[start][0]=0;
que.push(qnode(start, 0, 0));
qnode tmp;
while(!que.empty()){
tmp=que.top();
que.pop();
int u=tmp.v;
int k = tmp.tt;
if(vis[u][k])continue;
vis[u][k]=true;
for(int i=0;idist[u][k]+cost){
dist[v][k]=dist[u][k]+cost;
que.push(qnode(v,k,dist[v][k]));
}
if (k < K && !vis[v][k+1] && dist[v][k+1] > dist[u][k]) {
dist[v][k+1] = dist[u][k];
que.push(qnode(v, k+1, dist[v][k+1]));
}
}
}
}
void addedge(int u,int v,int w){
E[u].push_back(Edge(v,w));
}
int main() {
int T;
int N,M;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &N, &M, &K);
for (int i = 1; i <= N; i++)E[i].clear();
int u,v,w;
while (M--) {
scanf("%d%d%d", &u,&v, &w);
addedge(u,v,w);
}
Dijkstra(N, 1);
long long ans = INF;
for (int i = 0; i <= K; i++)
ans = min(ans, dist[N][i]);
printf("%lld\n", ans);
}
return 0;
}
https://blog.csdn.net/qq_36693533/article/details/78466623