【图论杂题】:L.motor [分层图]

本文探讨了一个经典的图论问题,即在给定的带权图中寻找从点S到点T的最短路径,特别关注在限定边数的情况下如何优化路径选择。通过使用分层图的概念和Dijkstra算法,作者详细解释了如何实现这一目标,并提供了完整的代码示例,强调了在pair排序中正确初始化的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

团队链接:motor

题面:

给定一张 n n n个点 m m m条边的带边权图
现在要从点 s s s到点 t t t
至多经过 k k k条边时可不花费代价
求最小代价

范围: n &lt; = 10000 , m &lt; = 50000 , k &lt; = 10 n&lt;=10000,m&lt;=50000,k&lt;=10 n<=10000,m<=50000,k<=10

样例:

输入:

5 10 1
1 5
1 2 4
1 4 3
2 4 2
2 5 100
5 3 24
4 5 12
2 1 1000
1 4 33
1 2 54
2 4 305

输出:

3
题解:

这个题,真没什么可说的,分层图板子题,,,之前写过的,但是之前自己画的那张图很不错,很好理解分层图,就再放一下吧。
但是,有一件很重要的事,要记录一下,djikstra+堆优化的时候,为什么不能把(S,0)写成(0,S),这是因为在pair中,两个变量是按第一关键字排序的!!!反过来的话就会按dis[]排序了,然后就WA,TLE等等(因为这个问题,调了一下午~~55555~)
在这里插入图片描述

代码

#include<bits/stdc++.h>
#define pii pair<int,int>  
#define fir first 
#define sec second 
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int ocean=2e9+7;
const int sea=1e7+7;
const int pool=2e6+7;
struct see{int ver,edge,next;}e[sea];
priority_queue<pii,vector<pii>,greater<pii> >Q;
int n,m,k,S,T,ans,tot,dis[pool],v[pool],last[sea];
void add(int x,int y,int z){e[++tot].edge=z,e[tot].ver=y;e[tot].next=last[x];last[x]=tot;}
void dijkstra()
{
	memset(dis,127,sizeof(dis));
	dis[S]=0; Q.push(make_pair(0,S));	
	while(Q.size())
	{
		int x=Q.top().sec; Q.pop();
		if(v[x]) continue; v[x]=1;
		for(int i=last[x];i;i=e[i].next)
		{
			int y=e[i].ver,z=e[i].edge;
			if(dis[y]>dis[x]+z)
			{
				dis[y]=dis[x]+z;
				Q.push(make_pair(dis[y],y));
			}
		}
	}
}
int main()
{
	n=read(); m=read(); k=read(); S=read(); T=read();
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		x=read(); y=read(); z=read();
		add(x,y,z); add(y,x,z);
		for(int j=1;j<=k;j++)
		add(j*n+x,j*n+y,z),add(j*n+y,j*n+x,z),
		add((j-1)*n+x,j*n+y,0),add((j-1)*n+y,j*n+x,0);
	}
	dijkstra(); ans=ocean;
	for(int i=0;i<=k;i++) ans=min(ans,dis[T+i*n]);
	printf("%d\n",ans);
	return 0;
}

Continue……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值