zoukankan      html  css  js  c++  java
  • 【bzoj2763】[JLOI2011]飞行路线

    *题目描述:
    Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

    *输入:
    数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。
    第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)
    接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)

    *输出:
    只有一行,包含一个整数,为最少花费。

    *样例输入:
    5 6 1
    0 4
    0 1 5
    1 2 5
    2 3 5
    3 4 5
    2 3 3
    0 2 100

    *样例输出:
    8

    *提示:
    对于30%的数据,2<=n<=50,1<=m<=300,k=0;
    对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;
    对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.

    *题解:
    有k次免票的最短路。
    好像直接spfa多计一个当前免票多少次好像就过了,据说有一种神奇的分层图的做法?

    *代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
    char B[1 << 15], *S = B, *T = B;
    inline int F()
    {
        R char ch; R int cnt = 0; R bool minus = 0;
        while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ? minus = 1 : cnt = ch - '0';
        while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus ? -cnt : cnt;
    }
    #define maxn 10010
    #define maxm 100010
    #define P std::pair<int, int>
    #define mkp std::make_pair
    #define fir first
    #define sec second
    int d[maxn][20];
    struct Edge
    {
        Edge *next;
        int to, w;
    }*last[maxn], e[maxm], *ecnt = e;
    inline void link(R int a, R int b, R int w)
    {
        *++ecnt = (Edge) {last[a], b, w}; last[a] = ecnt;
        *++ecnt = (Edge) {last[b], a, w}; last[b] = ecnt;
    }
    std::queue<P> q;
    bool inq[maxn][20];
    int main()
    {
    //  setfile();
        R int n = F(), m = F(), k = F(), s = F(), t = F();
        for (R int i = 1; i <= m; ++i)
        {
            R int a = F(), b = F(), w = F();
            link(a, b, w);
        }
        memset(d, 63, sizeof (d));
        q.push(mkp(s, 0)); d[s][0] = 0;
        while (!q.empty())
        {
            R P now = q.front(); q.pop();
            R int pos = now.fir, times = now.sec;
            inq[pos][times] = 0;
            for (R Edge *iter = last[pos]; iter; iter = iter -> next)
            {
                if (d[iter -> to][times] > d[pos][times] + iter -> w)
                {
                    d[iter -> to][times] = d[pos][times] + iter -> w;
                    if (!inq[iter -> to][times])
                    {
                        q.push(mkp(iter -> to, times));
                        inq[iter -> to][times] = 1;
                    }
                }
                if (times < k && d[iter -> to][times + 1] > d[pos][times])
                {
                    d[iter -> to][times + 1] = d[pos][times];
                    if (!inq[iter -> to][times + 1])
                    {
                        q.push(mkp(iter -> to, times + 1));
                        inq[iter -> to][times + 1];
                    }
                }
            }
        }
        R int ans = 0x7fffffff;
        for (R int i = 0; i <= k; ++i) cmin(ans, d[t][i]);
        printf("%d
    ", ans );
        return 0;
    }
  • 相关阅读:
    虚拟机安装配置
    大整数加法 面试题
    结构体
    操作文件
    Gcd HDU
    牛客练习赛47 A DongDong破密码 (异或性质,递推)
    ACM常用之 异或运算的性质。
    Wannafly挑战赛22 C 多项式(大数,多项式极限)
    大数全能模板
    Wannafly挑战赛22 D 整数序列 (线段树维护三角函数值)
  • 原文地址:https://www.cnblogs.com/cocottt/p/6764975.html
Copyright © 2011-2022 走看看