bzoj2763: [JLOI2011]飞行路线

Description

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

Input

数据的第一行有三个整数,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)
 

Output

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

Sample Input

5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100

Sample Output

8

HINT

 

对于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.

 

''建立分层图。
点 nt + i 表示已经改了 t 条边的边权, 从起点到 i 点的最短路长度。
那么对于任意一条边 (u, v, c)
在分层图建立无向边 (nt + u, nt + v, c)
与有向边 (nt + u, n(t + 1) + v, 0), (nt + v, n(t + 1) + u, 0)
直接跑最短路就好。''

——来自某课件

 1 #include <stdio.h>
 2 #include <queue>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define inf 2000000000
 6 using namespace std;
 7 typedef pair<long long , int > pii;
 8 struct node 
 9 {
10     int u, v, w, next;
11 }a[3000010*2];
12 int dis[200010];
13 int rp, T, first[200010], n, m, tot, k;
14 int done[200010];
15 void addedge(int st, int end, int val)
16 {
17     a[++tot].u = st;a[tot].v = end;a[tot].w = val;
18     a[tot].next =first[st];first[st] = tot;
19 }
20 int dij(int S)
21 {
22     priority_queue <pii, vector<pii>, greater<pii > > q;
23     memset(dis,0x7f,sizeof(dis));;
24     q.push(make_pair(0, S));
25     dis[S] = 0;
26     while (!q.empty())
27     {
28         int u = q.top().second;q.pop();
29         if(done[u])continue;
30         done[u] = 1;
31         for (int e = first[u]; e != -1; e = a[e].next)
32         {
33             int v = a[e].v;
34             if (dis[u] + a[e].w < dis[v])
35             {
36                 dis[v] = dis[u] + a[e].w;
37                 q.push(make_pair(dis[v], v));
38             }
39         }
40     }
41 }
42 int main()
43 {
44     int ST, END, x, y, z;
45     scanf("%d %d %d", &n, &m, &k);
46     scanf("%d %d", &ST, &END);
47     ST++;END++;
48     memset(first, -1, sizeof(first));
49      for (int i = 1; i <= m; i++)
50      {
51         scanf("%d %d %d", &x, &y, &z);
52         x++;y++;
53         for (int t = 0; t <= k; t++)
54         {
55             addedge(x+n*t, y+n*t, z);
56             addedge(y+n*t, x+n*t, z);
57             if(t == k)continue;
58             addedge(x+n*(t), n*(t+1)+y, 0);
59             addedge(y+n*(t), n*(t+1)+x, 0);
60         }
61      }
62      dij(ST);
63      int ans = inf;
64     for (int i = 0; i <= k; i++)
65         ans = min(dis[i*n+END], ans);
66        printf("%d\n", ans);
67      return 0;
68 }

 

转载于:https://www.cnblogs.com/z52527/p/4735387.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值