2763: [JLOI2011]飛行路線
Time Limit: 10 Sec Memory Limit: 128 MB
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.
1 #include <queue>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #define N 11000
6 #define M 51000
7 #define inf 0x3f3f3f3f
8 using namespace std;
9 struct KSD
10 {
11 int v,len,next;
12 }e[M<<1];
13 int head[N],cnt;
14 struct Lux
15 {
16 int x,y;
17 Lux(int a,int b):x(a),y(b){}
18 Lux(){}
19 };
20 void add(int u,int v,int len)
21 {
22 ++cnt;
23 e[cnt].v=v;
24 e[cnt].len=len;
25 e[cnt].next=head[u];
26 head[u]=cnt;
27 }
28 int n,m,p,s,t;
29 int dist[11][N];
30 bool in[11][N];/*spfa的dist,标記在每一層都要有*/
31 queue<Lux>q;
32 int spfa()
33 {
34 int i,v;
35 memset(dist,0x3f,sizeof(dist));
36 q.push(Lux(0,s));/*從第0層開始spfa*/
37 dist[0][s]=0;
38 in[0][s]=1;
39 while(!q.empty())
40 {
41 Lux U=q.front();
42 q.pop();
43 in[U.x][U.y]=0;
44
45 for(i=head[U.y];i;i=e[i].next)
46 {
47 v=e[i].v;/*先跑完這一層的最短路*/
48 if(dist[U.x][v]>dist[U.x][U.y]+e[i].len)
49 {
50 dist[U.x][v]=dist[U.x][U.y]+e[i].len;
51 if(!in[U.x][v])q.push(Lux(U.x,v)),in[U.x][v]=1;
52 }
53 }
54 if(U.x<p)for(i=head[U.y];i;i=e[i].next)
55 {/*如果還可以向下一層轉移的話,就把這個點出發的每一條邊都設為免費下一層轉移,因為要記錄每個點dist到底用了幾個免費的路線,是以用二維數組--分層思想*/
56 v=e[i].v;
57 if(dist[U.x+1][v]>dist[U.x][U.y])
58 {
59 dist[U.x+1][v]=dist[U.x][U.y];
60 if(!in[U.x+1][v])q.push(Lux(U.x+1,v)),in[U.x+1][v]=1;
61 }
62 }
63 }
64
65 int ret=inf;
66 for(i=0;i<=p;i++)ret=min(ret,dist[i][t]);/*在每一層中都找到t的最小值(最多k條免費),為什麼要在每一層都找,而不是隻在最後一層尋找呢。假設有這麼一種情況,由s--t的最少的路上的途徑數目少于k條,那麼在k之前的某一層上就有dis=0,但是如果必須使用k條路徑的話,那麼就會找的一條路途數多于k的路來滿足這個條件,那麼隻用第k層的dis自然不是正确結果了。*/
67 return ret;
68 }
69
70 int main()
71 {
72 // freopen("test.in","r",stdin);
73 int i,j,k;
74 int a,b,c;
75 scanf("%d%d%d%d%d",&n,&m,&p,&s,&t);
76 for(i=1;i<=m;i++)
77 {
78 scanf("%d%d%d",&a,&b,&c);
79 add(a,b,c);/*無向圖建立雙向邊*/
80 add(b,a,c);
81 }
82 printf("%d\n",spfa());
83 return 0;
84 }
1 /*我的代碼*/
2 #define K 11
3 #include<iostream>
4 using namespace std;
5 #include<cstdio>
6 #include<queue>
7 #include<cstring>
8 #define N 10010
9 #define M 50010
10 struct QU{
11 int ce,bh;
12 };
13 struct Edge{
14 int v,w,last;
15 }edge[M<<1];
16 int head[N],dis[K][N],k,n,m,t=0,sta,en;
17 bool inque[K][N];
18 inline int read()
19 {
20 int ff=1,ret=0;
21 char s=getchar();
22 while(s<'0'||s>'9')
23 {
24 if(s=='-') ff=-1;
25 s=getchar();
26 }
27 while(s>='0'&&s<='9')
28 {
29 ret=ret*10+s-'0';
30 s=getchar();
31 }
32 return ret*ff;
33 }
34 void add_edge(int u,int v,int w)
35 {
36 ++t;
37 edge[t].v=v;
38 edge[t].w=w;
39 edge[t].last=head[u];
40 head[u]=t;
41 }
42 void input()
43 {
44 n=read();m=read();k=read();
45 sta=read();en=read();
46 int a,b,c;
47 for(int i=1;i<=m;++i)
48 {
49 a=read();b=read();c=read();
50 add_edge(a,b,c);
51 add_edge(b,a,c);
52 }
53 }
54 void SPFA()
55 {
56 memset(dis,100,sizeof(dis));/*注意指派的最大值不要超界*/
57 dis[0][sta]=0;
58 inque[0][sta]=true;
59 queue<QU>Q;
60 QU A;
61 A.ce=0;
62 A.bh=sta;
63 Q.push(A);
64 while(!Q.empty())
65 {
66 QU NOw=Q.front();
67 Q.pop();
68 inque[NOw.ce][NOw.bh]=false;
69 for(int l=head[NOw.bh];l;l=edge[l].last)
70 {
71 if(dis[NOw.ce][edge[l].v]>edge[l].w+dis[NOw.ce][NOw.bh])
72 {
73 dis[NOw.ce][edge[l].v]=edge[l].w+dis[NOw.ce][NOw.bh];
74 if(!inque[NOw.ce][edge[l].v])
75 {
76 inque[NOw.ce][edge[l].v]=true;
77 QU C;
78 C.bh=edge[l].v;
79 C.ce=NOw.ce;
80 Q.push(C);
81 }
82 }
83 }
84 if(NOw.ce==k) continue;
85 for(int l=head[NOw.bh];l;l=edge[l].last)
86 {
87 if(dis[NOw.ce+1][edge[l].v]>dis[NOw.ce][NOw.bh])
88 {
89 dis[NOw.ce+1][edge[l].v]=dis[NOw.ce][NOw.bh];
90 if(!inque[NOw.ce+1][edge[l].v])
91 {
92 inque[NOw.ce+1][edge[l].v]=true;
93 QU C;
94 C.bh=edge[l].v;
95 C.ce=NOw.ce+1;
96 Q.push(C);
97 }
98 }
99 }
100 }
101 }
102 int main()
103 {
104 input();
105 SPFA();
106 int ans=(1<<31)-1;
107 for(int i=0;i<=k;++i)
108 ans=min(ans,dis[i][en]);
109 printf("%d\n",ans);
110 return 0;
111 }
112