• JZOJ 1782. Travel


    题目

    Description

      给出一个有n个顶点m条边的有向图,对于一条边长度为len的边有两种走法。
      1、如果a和b可以互达,则走过这条边的时间为len
      2、如果a和b不可以互达,则走过这条边的时间为2*len
      现在给出一个k,问,从顶点1到顶点n,满足第二种走法不超过k次的最短时间是多少。
     

    Input

      第一行有3个整数n,m,k(1<=n<=100,1<=m<=10000,0<=k<=10),表示有n个顶点,m条边。
      接下来有m行,每行有3个整数xi,yi,leni(1<=xi,yi<=n,1<=leni<=10000),表示长度为leni的有向边。
      注意,两个点可能有多条边连接。

    Output

      一行一个整数,表示最短时间。
      如果没有满足题目条件的路径,则输出-1
     

    Sample Input

    7 7 3
    1 2 2
    1 3 2
    2 4 3
    4 7 5
    3 5 4
    5 6 1
    6 4 2

    Sample Output

    20
     

    Data Constraint

     
     

    Hint

    【数据约定】
      对于30%的数据n<=10,m<=10,
      对于100%的数据,如题目描述

     

    分析

     

    • 我们要判断两点间是否相互连通
    • 不单单只是两点能直接到达
    • 间接到达也是可以的
    • 所以我们跑一个Floyd
    • 就能判断是否连通啦
    • 然后要注意的一点是,我每一次跟新一次值都要放队列重新对其他点进行跟新

     

    代码

    #include<iostream> 
    #include<vector>
    #include<queue>
    #include<cstring> 
    using namespace std;
    int vis[201][201];
    int dp[201][20];
    int map[201][201];
    int flag[201];
    int fl[201][201];
    int n,m,k;
    vector<int> f[201]; 
    void spfa()
    {
        memset(dp,0x3f,sizeof(dp));
        queue<int> q; q.push(1);
        dp[1][0]=0; flag[1]=1;
        while (!q.empty())
        {
            int x=q.front(); q.pop(); flag[x]=0;
            for (int i=0;i<f[x].size();i++)
            {
                int y=f[x][i];
                if (fl[y][x]!=fl[0][0])
                {
                    for (int j=0;j<=k;j++)
                    if(dp[x][j]+map[x][y]<dp[y][j])
                    {
                      dp[y][j]=min(dp[y][j],dp[x][j]+map[x][y]);
                      if(!flag[y])
                      {
                          flag[y]=1;
                          q.push(y);
                      }
                    }
                     
                }
                else
                {
                    for (int j=1;j<=k;j++)
                    if(dp[x][j-1]+map[x][y]*2<dp[y][j])
                    {
                      dp[y][j]=min(dp[x][j-1]+2*map[x][y],dp[y][j]);
                      if(!flag[y])
                      {
                          flag[y]=1;
                          q.push(y);
                      }
                    }
                     
                }
            }
        }
    }
    int main ()
    {
        cin>>n>>m>>k;
        memset(map,0x3f,sizeof(map));
        memset(fl,0x3f,sizeof(fl));
        for (int i=1,x,y,z;i<=m;i++)
        {
            cin>>x>>y>>z;
            if (!vis[x][y])
            {
                f[x].push_back(y);
                vis[x][y]=1;
            }
            map[x][y]=min(map[x][y],z);
            fl[x][y]=min(fl[x][y],z);
        }
        for (int kk=1;kk<=n;kk++)
          for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
              if (i!=j&&i!=kk&&j!=kk&&fl[i][kk]+fl[kk][j]<fl[i][j])
                 fl[i][j]=fl[i][kk]+fl[kk][j];
        spfa();
        int ans=1e9;
        for (int i=0;i<=k;i++)
            ans=min(dp[n][i],ans);
        if (ans==1000000000) cout<<-1;
        else 
        cout<<ans;
    }
    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    noip2016十连测round1
    [bzoj 3732] Network (Kruskal重构树)
    主席树学习笔记
    [ZKW线段树]
    [poj2182] Lost Cows (线段树)
    [模板] 线性筛逆元
    [模板] 线筛欧拉函数
    [模板] SAP
    [poj2411] Mondriaan's Dream (状压DP)
    [poj2247] Humble Numbers (DP水题)
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/11158416.html
Copyright © 2020-2023  润新知