【bzoj2763】[JLOI2011]飞行路线

来源:互联网 发布:lol全皮肤软件 编辑:程序博客网 时间:2024/03/29 12:41

*题目描述:
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 secondint 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\n", ans );    return 0;}
0 0