L——Magical Girl Haze 【Dijkstra演算法+分層圖思想】
- 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
題解思路:迪傑斯特拉最短路+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 <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=100003;
const int INF=0x3f3f3f3f;
struct HeapNode
{
ll d;
int u;
HeapNode(ll _d=0,int _u=0):d(_d),u(_u){}
bool operator <(const HeapNode &rhs)const
{
return d>rhs.d;
}
};
struct Edge
{
int from;
int to;
ll dist;
Edge(int u=0,int v=0,ll dist=0):from(u),to(v),dist(dist){}
};
vector<Edge>edges;
vector<int>G[maxn];
void add_edges(int from,int to,ll dist)
{
edges.push_back(Edge(from,to,dist));
int m=edges.size();
G[from].push_back(m-1);
}
void init(int n)
{
for(int i=0;i<n;i++)
{
G[i].clear();
}
edges.clear();
}
int n,m,k;
bool vis[maxn][11];//永久標記
ll d[maxn][11];//dp距離陣列,層次圖
void dijkstra(int s,int n,int k)
{
memset(vis,false,sizeof(vis));
priority_queue<HeapNode>Q;
memset(d,INF,sizeof(d));
Q.push(HeapNode(0,s));
//vis[s][0]=true;
d[s][0]=0;
while(!Q.empty())
{
HeapNode x=Q.top();Q.pop();
int lev=x.u/(n+1);//表示使Z條邊的長度為0
int u=x.u%(n+1);
if(vis[u][lev])continue;
vis[u][lev]=true;
for(int i=0;i<G[u].size();i++)
{
Edge &e=edges[G[u][i]];
if(vis[e.to][lev])continue;
//選擇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));
}
if(lev==k)continue;
//選擇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));
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int u,v;
ll cost;
scanf("%d%d%d",&n,&m,&k);
init(n);
for(int i=0;i<m;i++)
{
scanf("%d%d%lld",&u,&v,&cost);
add_edges(u,v,cost);
}
dijkstra(1,n,k);
printf("%lld\n",d[n][k]);
}
return 0;
}