题目描述
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在nn个城市设有业务,设这些城市分别标记为00到n-1n−1,一共有mm种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多kk种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
输入格式
数据的第一行有三个整数,n,m,kn,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,ts,t,分别表示他们出行的起点城市编号和终点城市编号。
接下来有m行,每行三个整数,a,b,ca,b,c,表示存在一种航线,能从城市aa到达城市bb,或从城市bb到达城市aa,价格为cc。
输出格式
只有一行,包含一个整数,为最少花费。
输入输出样例
输入 #1
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
输出 #1
8
数据范围
解题技巧
这题一看第一眼就是分层图,感觉就是很简单,然后就发现自己死了,发现K这个东西一直不好处理,然后就想,可以建K层,每一层都是完全图,然后第Z层就表示是滴Z次免费的情况,把当前点的所有出边都往下面连一个费用是0的单向边,由于在坐飞机时可以是双向边,所以当前点的指向点就要从上一层连向下一层的当前点,写成代码就是这样
1 for(int i=1;i<=m;i++) 2 { 3 scanf("%d%d%d",&x,&y,&w); 4 add(x,y,w); 5 add(y,x,w); 6 for(int j=1;j<=k;j++) 7 { 8 add(x+(j*n),y+(j*n),w); 9 add(y+(j*n),x+(j*n),w); 10 add(x+((j-1)*n),y+(j*n),0); 11 add(y+((j-1)*n),x+(j*n),0); 12 } 13 }
但要注意一点,假如在第二层就可以跑到终点,但最后我们输出的答案是第K层的终点的DIS,所以每一层的终点都要往下一层的终点连一条费用为0的边,不然会出事
1 for(int i=1;i<=k;i++) 2 { 3 add(t+(i-1)*n,t+i*n,0); 4 }
,最后就跑一下dijkstra就行了,感觉还是最好不要用SPFA,被NOI搞的总感觉会挂掉,虽然不止一个大佬和老师说过NOIP的题目数据水。。。
最后放一下完整的代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int maxn=1e6+10; 7 int n,m,k,s,t; 8 int x,y,w; 9 struct edge 10 { 11 int to; 12 int value; 13 int next; 14 }way[maxn*6]; 15 int tot; 16 int dis[maxn]; 17 bool vis[maxn]; 18 int head[maxn]; 19 void add(int x,int y,int w) 20 { 21 way[++tot].next=head[x]; 22 way[tot].to=y; 23 way[tot].value=w; 24 head[x]=tot; 25 } 26 struct node 27 { 28 int dist,id; 29 node(){} 30 node(int dist,int id):dist(dist),id(id){} 31 }; 32 bool operator <(node xi,node yi) 33 { 34 return xi.dist>yi.dist; 35 } 36 int dijkstra(int s) 37 { 38 priority_queue< node >q; 39 memset(dis,0x3f,sizeof(dis)); 40 memset(vis,0,sizeof(vis)); 41 q.push(node(0,s)); 42 dis[s]=0; 43 while(!q.empty()) 44 { 45 node t(q.top()); 46 q.pop(); 47 int x=t.id; 48 if(vis[x]) 49 { 50 continue; 51 } 52 vis[x]=1; 53 for(int i=head[x];i;i=way[i].next) 54 { 55 int to=way[i].to; 56 if(dis[to]>way[i].value+t.dist) 57 { 58 dis[to]=way[i].value+t.dist; 59 q.push(node(dis[to],to)); 60 } 61 } 62 } 63 } 64 int main() 65 { 66 memset(head,0,sizeof(head)); 67 scanf("%d%d%d",&n,&m,&k); 68 scanf("%d%d",&s,&t); 69 for(int i=1;i<=m;i++) 70 { 71 scanf("%d%d%d",&x,&y,&w); 72 add(x,y,w); 73 add(y,x,w); 74 for(int j=1;j<=k;j++) 75 { 76 add(x+(j*n),y+(j*n),w); 77 add(y+(j*n),x+(j*n),w); 78 add(x+((j-1)*n),y+(j*n),0); 79 add(y+((j-1)*n),x+(j*n),0); 80 } 81 } 82 for(int i=1;i<=k;i++) 83 { 84 add(t+(i-1)*n,t+i*n,0); 85 } 86 dijkstra(s); 87 printf("%d",dis[t+k*n]); 88 }