BZOJ2763: [JLOI2011]飞行路线

2763: [JLOI2011]飞行路线

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2112  Solved: 802
[Submit][Status][Discuss]

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.


 


显然有两种做法:

S1:记dis[x][i]为为到了第x个点的并且用了i次免费机会的最小花费,直接最短路就可以了

s2:将点拆分为n*(k+1) 个,构成分层图,每一点表示的是当前点用了k次免费的情况(如果x与y相连,就需要将x连向y的下一层)


 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<vector>
 6 #include<cmath>
 7 #define llg long long 
 8 #define maxn 200010 
 9 using namespace std;
10 vector <llg> a[maxn],val[maxn];
11 llg i,j,k,x,n,m,y,f,t,z,dl[maxn*10],w,dis[maxn],tail,head,v;
12 void link(llg x,llg y,llg z)
13 {
14      for (llg i=0;i<k;i++)
15      {
16          llg xx=x*(k+1)+i,yy=y*(k+1)+i;
17          a[xx].push_back(yy+1),val[xx].push_back(0);
18          a[yy].push_back(xx+1),val[yy].push_back(0);
19          a[xx].push_back(yy),val[xx].push_back(z);
20          a[yy].push_back(xx),val[yy].push_back(z);
21      }
22      llg i=k;
23      llg xx=x*(k+1)+i,yy=y*(k+1)+i;
24      a[xx].push_back(yy),val[xx].push_back(z);
25      a[yy].push_back(xx),val[yy].push_back(z);
26 }
27 int main()
28 {
29    // freopen("a.in","r",stdin); freopen("a.out","w",stdout);
30     cin>>n>>m>>k>>f>>t;
31     n*=(k+1);
32     for (i=1;i<=m;i++)
33         {
34           scanf("%lld%lld%lld",&x,&y,&z);
35           link(x,y,z); 
36         }
37     tail=1; head=0;
38     dl[1]=f*(k+1); for (i=0;i<=200001;i++) dis[i]=0x7fffffff; for (i=0;i<=k;i++) dis[f*(k+1)+i]=0;
39     do{
40        head++,head=(head-1)%1000000+1;
41        x=dl[head];
42        w=a[x].size();
43        for (i=0;i<w;i++)
44            {
45             v=a[x][i];
46             if (dis[v]>dis[x]+val[x][i])
47             {
48              dis[v]=dis[x]+val[x][i];
49              tail++,tail=(tail-1)%1000000+1;
50              dl[tail]=v;
51             }
52            }
53     }while (head!=tail);
54     llg ans=0x7fffffff;
55     for (i=0;i<=k;i++) ans=min(ans,dis[t*(k+1)+i]);
56     cout<<ans;
57     return 0;
58 } 

 

 

posted @ 2016-07-30 17:15  №〓→龙光←  阅读(172)  评论(0编辑  收藏  举报