1. 程式人生 > 其它 >【分層圖最短路】【學習筆記】

【分層圖最短路】【學習筆記】

【分層圖最短路】【學習筆記】

例題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)\in 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;
}