https://nanti.jisuanke.com/t/18018
再最短路的过程中。
维护一个 dp[i][j]
表示从起点到达i,走了j个地下通道。(地下通道数目很少。)
边松弛边维护。
用dij和spfa都行。
注意一点,就是添加的地下通道的数目不要多于总的数目。
(dij自己写的一直错。。。今晚心态炸了)
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=6e3;
struct Node{
ll to;
ll cost;
bool type;
Node(){};
Node(int _to,int _cost,bool _type){
cost=_cost;
type=_type;
to=_to;
}
};
vector<Node>G[maxn];
void add(int a,int b,int c,int d){
if(d==0){
G[a].push_back(Node(b,c,false));
G[b].push_back(Node(a,c,false));
}
else{
G[a].push_back(Node(b,c,true));
G[b].push_back(Node(a,c,true));
}
}
int dist[maxn][60];
bool vis[maxn][60];
struct node2
{
int u,len;
}now,nex;
ll l;
int n1;
void SPFA(int n)
{
queue<node2>s;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
for(int j=0;j<=320;j++)
{
dist[i][j]=0x3f3f3f3f;
}
}
dist[1][0]=0;
now.len=0;
now.u=1;
s.push(now);
while(!s.empty())
{
now=s.front();s.pop();
int u=now.u;
int len=now.len;
vis[u][len]=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].to;
int w=G[u][i].cost;
int flag=G[u][i].type;
if(dist[v][len+flag]>=dist[u][len]+w)
{
dist[v][len+flag]=dist[u][len]+w;
if(vis[v][len+flag]==0&&len+flag<=n1)
{
vis[v][len+flag]=1;
nex.u=v;nex.len=len+flag;
s.push(nex);
}
}
}
}
int output=0x3f3f3f3f;
for(int i=0;i<=320;i++)
{
if(dist[n][i]<=l)
output=min(output,dist[n][i]-i);
}
if(output==0x3f3f3f3f)output=-1;
printf("%d\n",output);
}
void init(){
for(int i=0;i<maxn;i++) G[i].clear();
memset(dist,0x3f,sizeof(dist));
}
int main()
{ int t;
int m,n2;
ll a1,b1,c1;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d",&m,&n1,&n2,&l);
init();
for(int i=1;i<=n1;i++){
scanf("%lld%lld",&a1,&b1);
add(a1,b1,1,true);
}
for(int i=1;i<=n2;i++){
scanf("%lld%lld%lld",&a1,&b1,&c1);
add(a1,b1,c1,false);
}
SPFA(m);
}
return 0;
}