[JLOI2011]飞行路线

[JLOI2011]飞行路线

BZOJ
luogu
新套路---分层图最短路
就是把原图复制成k层,一个点i拆成a×n+i,\(a\in [0,k]\)
免费一条路相当于升一层,但是注意只升不能降
所以不同层连向上的单向边
比如一条边(u,v),拆成(a×n+u,a×n+v),(a×n+u,(a+1)×n+v),(a×n+v,(a+1)×n+u),(a×n+u,(a+1)×n+v)
然后跑一个dijkstra

#include<bits/stdc++.h>
using namespace std;
const int _=2e5+5;
int re(){
	int x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*w;
}
int n,m,k,s,t,cnt;
int h[_],d[_];
bool vis[_];
struct node{int id,d;};
struct edge{int to,next,w;}e[_*13];
bool operator <(node a,node b){return a.d>b.d;}
priority_queue<node>q;
void link(int u,int v,int w){
	e[++cnt]=(edge){v,h[u],w};h[u]=cnt;
}
void dij(){
	memset(d,63,sizeof(d));
	d[s]=0;q.push((node){s,0});
	while(!q.empty()){
		int u=q.top().id;q.pop();vis[u]=1;
		for(int i=h[u];i;i=e[i].next){
			int v=e[i].to;
			if(d[v]>d[u]+e[i].w){
				d[v]=d[u]+e[i].w;
				if(!vis[v])q.push((node){v,d[v]});
			}
		}
	}
}
int main(){
	n=re(),m=re(),k=re();s=re(),t=re();
	while(m--){
		int a=re(),b=re(),c=re();
		link(a,b,c);link(b,a,c);
		for(int i=1;i<=k;i++){
			link(i*n+a,i*n+b,c);
			link(i*n+b,i*n+a,c);
			link((i-1)*n+a,i*n+b,0);
			link((i-1)*n+b,i*n+a,0);
		}
	}
	for(int i=0;i<k;i++)
		link(i*n+t,(i+1)*n+t,0);
	dij();
	printf("%d\n",d[k*n+t]);
	return 0;
}
posted @ 2018-11-03 20:17  sdzwyq  阅读(139)  评论(0编辑  收藏  举报