计蒜客&景驰1024-二维最短路&模板-热爱工作的蒜蒜

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值