【分层图最短路】【学习笔记】

【分层图最短路】【学习笔记】

例题1
分析:
设f[i][j]为从1走到i,已指定j条路径边权为0,边权和的最小值,那么有
f[i][j]+w[i,y]——>f[y][j],
f[i][j]——>f[y][j+1],(i,y)E
f[1][0]=0.
则答案为f[n][k]
实际上就是求从(1,0)到(n,k)的最短路,但可以不用真的建出分层图,注意判断不要让j超过k。
因为边权非负,用dij转移即可。

Code

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read()
{
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') {w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=~(x-1);
if(x>9) write(x/10);
putchar('0'+x%10);
}
const int N=1e4+100;
int n,m,k,d[N][22],vis[N][22];
int hd[N],cnt;
struct node{
int nxt,to,w;
}e[N*10];
void add(int x,int y,int z)
{
e[++cnt].nxt=hd[x];
e[cnt].w=z;
e[cnt].to=y;
hd[x]=cnt;
}
priority_queue<pair<int,pair<int,int> > >q;
void dij()
{
memset(d,0x3f,sizeof d);
d[1][0]=0;
q.push(make_pair(0,make_pair(1,0)));
while(q.size())
{
pair<int,int>x=q.top().second;q.pop();
int f=x.first,s=x.second;
if(vis[f][s]) continue;
vis[f][s]=1;
for(int i=hd[f];i;i=e[i].nxt)
{
int y=e[i].to;
if(d[y][s]>d[f][s]+e[i].w) d[y][s]=d[f][s]+e[i].w,q.push({-d[y][s],{y,s}});
if(s<k&&d[y][s+1]>d[f][s]) d[y][s+1]=d[f][s],q.push({-d[y][s+1],{y,s+1}});
}
}
}
int main()
{
n=read();m=read();k=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
dij();
write(d[n][k]);
return 0;
}

例题2
与上一题类似,用dij求解即可。

Code

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read()
{
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') {w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=~(x-1);
if(x>9) write(x/10);
putchar('0'+x%10);
}
const int N=55,M=1e3+100;
int hd[N],cnt;
struct node{
int nxt,to,w;
}e[M<<1];
void add(int x,int y,int z)
{
e[++cnt].w=z;
e[cnt].to=y;
e[cnt].nxt=hd[x];
hd[x]=cnt;
}
int f[N][N],n,m,k,vis[N][N];
priority_queue<pair<int,pair<int,int> > >q;
void dij()
{
memset(f,0x3f,sizeof f);
for(int i=0;i<=k;++i) f[1][i]=0,q.push({0,{1,i}});
while(q.size())
{
int x=q.top().second.first,y=q.top().second.second;q.pop();
if(vis[x][y]) continue;
vis[x][y]=1;
if(x==n&&y==k) return;
for(int i=hd[x];i;i=e[i].nxt)
{
int j=e[i].to;
if(f[j][y]>f[x][y]+e[i].w)f[j][y]=f[x][y]+e[i].w,q.push({-f[j][y],{j,y}});
if(y<k&&f[j][y+1]>f[x][y]+e[i].w/2) f[j][y+1]=f[x][y]+e[i].w/2,q.push({-f[j][y+1],{j,y+1} });
}
}
}
signed main()
{
n=read();m=read();k=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
dij();
write(f[n][k]);
return 0;
}

总结:
分层图最短路可以看做一种特殊的dp,列出状态转移方程以后,利用最短路算法来求解即可。
另外,分层图中的边一般不用真的建出来,这样也可以节省空间复杂度。

posted @   glq_C  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示