P4568 [JLOI2011]飞行路线

P4568 [JLOI2011]飞行路线

题意:

n个城市,m个航班,你有k次免费坐航班的机会,问从s到t最少花费是多少?

题解:

分层图问题
简单说说什么是分层图:
其实就是将一个平面的图重新建图,有好几层
具体的说每层图之间各自连边与原图一样,但是相邻的两层图之间根据原来的关系进行连边
虽然是多层图,但是用一维的关系就可以
比如:
当有3个点,3层图时
1对应的就是 1+n 和 1+2 * n
2对应的就是 2+n 和 2+2 * n

当存在n个点,k层图时,
1对应的就是1+n * 0, 1+ n* 1…1+n * (k-1)
而且每一层的图都遵循只能从上面的图到下一层图,不能反过来
那建这么多层图的目的是什么呢?
你可以理解成是一种尝试,就比如本题,我们向下一层就代表拥有一次免费乘坐的机会,如果我们有k次免费乘坐机会,就建k层图(最原本的是第0层)。
每层图内部是原本的边权关系,而图与图之间是0边权(就相当于是免费乘坐机会)

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
   ll s=0,w=1ll;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
void rd_test(){
	#ifdef ONLINE_JUDGE
	#else
		startTime = clock(); //计时开始
        freopen("in.txt","r",stdin);
	#endif
}
void Time_test(){
	#ifdef ONLINE_JUDGE
	#else
		endTime = clock(); //计时结束
   		printf("\n运行时间为:%lfs\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);
	#endif
}
const int maxn=3e5+9;
struct node{
	int w,now;
	inline bool operator<(const node &x)const{
		return w>x.w;
	} 
};
priority_queue<node>q;
int dis[maxn],vis[maxn];
vector<PII>vec[maxn];
int s,t;int n,m,k;
void dijkstra(){
	memset(dis,INF_int,sizeof(dis));
	dis[s]=0;
	q.push((node){0,s});
	while(!q.empty()){
		node x=q.top();
		q.pop();
		int u=x.now;
		if(vis[u])continue;
		vis[u]=1;
		for(auto it:vec[u]){
			int v=it.first;
			int w=it.second;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push({dis[v],v});
			}
		}
	}
}

int main()
{
	//rd_test();
	cin>>n>>m>>k;
	cin>>s>>t;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		vec[u].push_back({v,w});
		vec[v].push_back({u,w});
		for(int j=1;j<=k;j++){
			//每一层
			vec[u+j*n].push_back({v+j*n,w});
			vec[v+j*n].push_back({u+j*n,w});
			
			//层与层之间 
			vec[u+(j-1)*n].push_back({v+j*n,0});
			vec[v+(j-1)*n].push_back({u+j*n,0});
		}
	}
	dijkstra();
	int minn=INF_int;
	for(int i=0;i<=k;i++){
		minn=min(minn,dis[t+i*n]);
	}
	cout<<minn;
	return 0;
	//Time_test();
}




上一篇:abc226E - Just one


下一篇:27:时间序列表示