热爱工作的蒜蒜(带限制最短路)

众所周知,蒜蒜是一名热爱工作的好员工,他觉得时间就是金钱,做事情总是争分夺秒。

这天晚上,蒜蒜一个人去吃晚饭。不巧的是,吃完饭以后就开始下雨了,蒜蒜并没有带雨伞出来。但是蒜蒜热爱工作,工作使他快乐,他要尽快赶回去写代码。

蒜蒜的公司在中关村,中关村这边地形复杂,有很多天桥、地下通道和马路交错在一起。其中,地下通道是可以避雨的,天桥和马路都没办法避。可以把中关村抽象成为 nnn 个点的地图(顶点编号为 111nnn),其中有 m1m_1m1 条地下通道,有 m2m_2m2 条马路或者天桥,其中地下通道的长度为 111。蒜蒜吃饭的地方在 111 点,公司在 nnn 点。当然,蒜蒜虽然爱工作心切,但是他更不想淋很多雨,同时也不想浪费很多时间。于是他折中了一下——在保证他回到公司所走的路程总和小于等于 LLL 的情况下,他希望淋雨的路程和尽量的少。

请你赶紧帮热爱工作的蒜蒜规划一条路径吧,不要再让他浪费时间。

输入格式

第一行输入测试组数 T(1≤T≤20)T(1 \le T \le 20)T(1T20)

接下来 TTT 组数据。

每一组数据的第一行输入四个整数 n(2≤n≤100)n(2 \le n \le 100)n(2n100)m1(0≤m1≤50)m_1(0 \le m_1 \le 50)m1(0m150)m2(0≤m2≤5000)m_2(0 \le m_2 \le 5000)m2(0m25000)L(1≤L≤108)L(1 \le L \le 10^8)L(1L108)

接下里 m1m_1m1 行,每行输入两个整数 a,b(1≤a,b≤n)a, b(1 \le a, b \le n)a,b(1a,bn),表示 aaabbb 之间有一条地下通道。

接下里 m2m_2m2 行,每行输入三个整数 u,v(1≤u,v≤n),c(1≤c≤106)u, v(1 \le u, v \le n), c(1 \le c \le 10^6)u,v(1u,vn),c(1c106),表示 uuuvvv 之间有一条长度为 ccc 的马路或者天桥。

所有路径都是双向的

输出格式

对于每组数据,如果有满足要求的路径,输出一个整数,表示淋雨的路程长度,否则输出 −1-11

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
int k[105][105];
int cases,n,m1,m2,l;
struct node
{
    int to;
    int w;
    node(int a,int b):to(a),w(b){}
};
int dist[105];
int dp[105];
int vis[105];
vector<node>G[105];
void dij()
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<=n;i++) dp[i] = inf,dist[i] = inf;
    queue<int>q; q.push(1); vis[1] = 1; dist[1] = 0; dp[1] = 0;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        int len = G[u].size(); vis[u] = 0;
        for(int i=0;i<len;i++)
        {
            int v = G[u][i].to;
            int w = G[u][i].w;
            if(dp[v]>dp[u] + w&&dist[u] + w<=l)
            {
                dp[v] = dp[u] + w;
                dist[v] = dist[u] + w;
                if(!vis[v]){ vis[v] = 1; q.push(v); }
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(!k[u][i]) continue;
            if(dp[i]>dp[u]&&dist[u] + 1<=l)
            {
                dp[i] = dp[u];
                dist[i] = dist[u] + 1;
                if(!vis[i]){ vis[i] = 1; q.push(i); }
            }
        }
    }
    if(dist[n]<=l&&dp[n]<=l) printf("%d\n",dp[n]);
    else printf("-1\n");
}
int main()
{
    int u,v,w;
    scanf("%d",&cases);
    while(cases--)
    {
        scanf("%d%d%d%d",&n,&m1,&m2,&l);
        memset(k,0,sizeof(k));
        for(int i=0;i<=n;i++) G[i].clear();
        for(int i=0;i<m1;i++)
        {
            scanf("%d%d",&u,&v);
            k[u][v] = 1; k[v][u] = 1;
        }
        for(int i=0;i<m2;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(node(v,w));
            G[v].push_back(node(u,w));
        }
        dij();
    }
    return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值