L——Magical Girl Haze 【Dijkstra算法+分层图思想】

本文介绍了一种结合迪杰斯特拉最短路径算法与动态规划的方法,用于解决特定类型的图论问题。该问题涉及在一个带有若干条可免费使用的边的城市网络中寻找从起点到终点的最短路径。

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

  • 1000ms
  • 262144K

description:
There are N cities in the country, and M directional roads from u to v(1≤u,v≤n). Every road has a distance ci​. Haze is a Magical Girl that lives in City 1, she can choose no more than K roads and make their distances become 0. Now she wants to go to City N, please help her calculate the minimum distance.

Input
The first line has one integer T(1≤T≤5), then following T cases.

For each test case, the first line has three integers N,M and K.

Then the following M lines each line has three integers, describe a road, Ui​,Vi​,Ci​. There might be multiple edges between u and v.

It is guaranteed that N≤100000,M≤200000,K≤10,
0 ≤Ci​≤1e9. There is at least one path between City 1 and City N.

Output
For each test case, print the minimum distance.

样例输入:
1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2
样例输出:
3

题目来源:2018ACM-ICPC南京赛区预赛

题解思路:迪杰斯特拉最短路+dp分层图思想,将距离数组设置为dist[maxn][11],则dist[i][j]表示从起点开始到i节点,途中将j条路径免费的最短路距离。分层图又是什么意思呢?以免费路径相同的为一层,这样在松弛时可以选择是否让当前的边变为0,代码如下:
1.选择这条边不为0

if(d[e.to][lev]>d[u][lev]+e.dist)
{
    d[e.to][lev]=d[u][lev]+e.dist;
    Q.push(HeapNode(d[e.to][lev],lev*(n+1)+e.to));
}

2.选择这条边为0,进入下一层,,则dist[e.to][lev]变为dist[e.to][lev+1]因为多让一条边变为0

if(d[e.to][lev+1]>d[u][lev])
{
     d[e.to][lev+1]=d[u][lev];
     Q.push(HeapNode(d[e.to][lev+1],(lev+1)*(n+1)+e.to));
}

这样,全部代码就写出来了。
ps:分层图还是第一次碰到,图上dp也不会做,还得好好补补。

#include<bits/stdc++.h>
using namespace std;
 
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
 
const int maxn=1e5+10;
int n,m,k,s,t;
 
struct qnode{
    int v,dis,level;
    qnode(int v=0,int dis=0,int level=0):v(v),dis(dis),level(level) {}
    bool operator<(const qnode &r)const
    {
        return dis>r.dis;
    }
};
struct Edge{
	int v,w;
	Edge(int v=0,int w=0):v(v),w(w) {} 
};
vector<Edge> ve[maxn];
ll d[maxn][11];
bool vis[maxn][11];
 
void addEdge(int u,int v,int w)
{
	ve[u].push_back(Edge(v,w));
}
void dijkstra(int start)
{
	mem(vis,false);
	mem(d,inf);
	priority_queue<qnode> q;
	d[start][0]=0;
	
	q.push(qnode(start,0,0));
	qnode tmp;
	while(!q.empty())
	{
		tmp=q.top();
		q.pop();
		int u=tmp.v;
		int lv=tmp.level;
		if(vis[u][lv])continue;
		vis[u][lv]=true;
		for(int i=0; i<ve[u].size(); i++)
		{
			int v=ve[u][i].v;
			int w=ve[u][i].w;
			
			if(w+d[u][lv]<d[v][lv])
			{
				d[v][lv]=w+d[u][lv];
				q.push(qnode(v,d[v][lv],lv));
			}
			
			if(lv<k)
			{
				if(d[u][lv]<d[v][lv+1])
				{
					d[v][lv+1]=d[u][lv];
					q.push(qnode(v,d[v][lv+1],lv+1));
				}
			}
		}
	}
}
int main()
{
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		scanf("%d%d",&s,&t);
		for(int i=0; i<=n; i++)ve[i].clear();
		for(int i=0; i<m; i++)
		{
			int u,v,w;scanf("%d%d%d",&u,&v,&w);
			addEdge(u,v,w);
			addEdge(v,u,w);
		}
		
		dijkstra(s);
		ll ans=d[t][0];
		for(int i=0; i<=k; i++)ans=min(ans,d[t][i]);
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值