P4568 [JLOI2011]飞行路线题解,也是分层图模板。
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
class node
{
	public:
		int next,len,end;
}e[5000000];
class node2
{
	public:
		int name,dis;
};
bool operator < (node2 a,node2 b)
{
	return a.dis>b.dis;
}
int head[200005]={0},cnt=0,n,m,dis[200005]={0},vis[200005]={0},k,s,en,ans=0x3f3f3f3f;
priority_queue<node2>q;
void add(int x,int y,int len)
{
	e[++cnt]=(node){head[x],len,y};
	head[x]=cnt;
}
void dijkstra(int);
int main()
{
	cin>>n>>m>>k;
	cin>>s>>en;
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
        //***
		for(int j=0;j<=k-1;j++)
		{
			add(n*j+a,n*j+b,c);
			add(n*j+b,n*j+a,c);
			add(n*j+a,n*(j+1)+b,0);
			add(n*j+b,n*(j+1)+a,0);
		} 
		add(n*k+a,n*k+b,c);
		add(n*k+b,n*k+a,c);
        //***核心代码
	}
	dijkstra(s);
	for(int i=0;i<=k;i++)
		ans=min(ans,dis[i*n+en]);//坑点
	cout<<ans;
	return 0;
} 
void dijkstra(int x)//喜闻乐见的dijkstra
{
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[x]=vis[x]=0;
	q.push((node2){x,dis[x]});
	while(!q.empty())
	{
		int tnext=q.top().name;
		q.pop();
		vis[tnext]=1;
		for(int i=head[tnext];i;i=e[i].next) 
		{
			int tend=e[i].end;
			if(vis[tend])
				continue; 
          	if(dis[tend]>dis[tnext]+e[i].len)
          	{
          		dis[tend]=dis[tnext]+e[i].len;
				q.push((node2){tend,dis[tend]});
			}
		}
	}
	return;
}
思路
分层图啊!
for(int j=0;j<=k-1;j++)
{
	add(n*j+a,n*j+b,c);
	add(n*j+b,n*j+a,c);
	add(n*j+a,n*(j+1)+b,0);
	add(n*j+b,n*(j+1)+a,0);
} 
add(n*k+a,n*k+b,c);
add(n*k+b,n*k+a,c);
分层图简介
分层图类似于一层一层的结构,因此得名。
典型题目就是普通的最短路 + 有 次免费边权。
Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?
这就是板子题啊!
.png)
一张无向有权图。设上面的图中,。
则要建2层图,层与层间连一条有向,边权为0的边。
.png)
也就是说,跑一边这个整个分层图的最短路即可!
总结
建一张k+1层的图,层与层之间以边权为  的有向边连接。再跑一边这整个图的最短路。取各层终点的  值。
彩蛋
P2939 [USACO09FEB]改造路Revamping Trails
3倍经验!
本文作者:Yurchiu
本文链接:https://yz-hs.github.io/0ab70095e346/
版权声明:本博客中所有原创文章除特别声明外,均允许规范转载,转载请注明出处。所有非原创文章,按照原作者要求转载。
 