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 #include2 #include 3 #include 4 #include 5 #define inf 2000000000 6 using namespace std; 7 typedef pair 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 , greater > 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 }