P2939 [USACO09FEB]改造路Revamping Trails

题面

这是一道分层图的模板题(大家都这么说),这使得我这个从来没有学过分层图的蒟蒻不知如何是好

网上的讲解我也都看不懂,或者说好像没找到讲解。。

在跟DDOSvoid大佬进行一番不知所云的交流过后,我忽然明白了这个东西


所谓分层图,就像它的名字一样,把图分成一层一层的,上一层可以到达下一层,但反过来不行

对于不同的题有不同的方法来分。以这道题为例,我们可以把图分为\(k+1\)层,每过一层表示添加了一条高速公路,\(d[u][k]\)表示到\(u\)点有\(k\)条高速公路最快多长时间,那么就可以跑最短路了

在跑最短路的时候我们只需要多判断一个把当前边变为高速公路是否可行即可

下放代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#include<queue>
#define ll long long
#define gc getchar
#define maxn 10005
#define maxm 50005
using namespace std;

inline ll read(){
	ll a=0;int f=0;char p=gc();
	while(!isdigit(p)){f|=p=='-';p=gc();}
	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
	return f?-a:a;
}int n,m,k;ll ans;

struct ahaha{
	int w,to,next;
}e[maxm<<1];int tot,head[maxn];
inline void add(int u,int v,int w){
	e[tot]={w,v,head[u]};head[u]=tot++;
}

struct ahaha1{
	int u,k;ll d;
	inline bool friend operator<(const ahaha1 x,const ahaha1 y){
		return x.d>y.d;
	}
};
ll d[maxn][25];int b[maxn][25];
priority_queue<ahaha1>q;
void dij(){memset(d,63,sizeof d);
	d[1][0]=0;q.push({1,0,0});
	while(!q.empty()){
		ahaha1 a=q.top();q.pop();
		int u=a.u;b[u][a.k]=0;
		for(int i=head[u];~i;i=e[i].next){
			int v=e[i].to;
			if(d[v][a.k]>d[u][a.k]+e[i].w){
				d[v][a.k]=d[u][a.k]+e[i].w;
				if(!b[v][a.k]){
					q.push({v,a.k,d[v][a.k]});
					b[v][a.k]=1;
				}
			}
			if(a.k<k&&d[v][a.k+1]>d[u][a.k]){
				d[v][a.k+1]=d[u][a.k];
				if(!b[v][a.k+1]){
					q.push({v,a.k+1,d[v][a.k+1]});
					b[v][a.k+1]=1;
				}
			}
		}
	}
}

int main(){memset(head,-1,sizeof head);
	n=read();m=read();k=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	dij();ans=21474836475486;
	for(int i=0;i<=k;++i)
		ans=min(ans,d[n][i]);
	printf("%lld\n",ans);
	return 0;
}

双倍经验P4568 [JLOI2011]飞行路线

posted @ 2019-02-21 15:50  子谦。  阅读(161)  评论(0编辑  收藏  举报
Live2D
//雪