飞行路线 HYSBZ - 2763 (分层图+Dijkstra && Spfa)

飞行路线

  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.

题解:

对于k次免费花费,我们可以把图想像为有k+1层,从第0层到第k层,第0层表示没有用过这k次机会,第i层表示用过i次免费花费。对于分层,有两种方法。本题为双向边。

注意:最后要从所有层中的终点找答案,因为如果s-t只有少于k条路,而你选取免费k次在到达终点的答案就可能不对。

1.建图时分层:建k+1层图。然后有边的两个点,多建一条到下一层边权为0的单向边,如果走了这条边就表示用了一次免费机会

比如共有N个点,1~n表示第一层,(1+n)~(n+n)代表第二层,(1+2*n)~(n+2*n)代表第三层,(1+i*n)~(n+i*n)代表第i层。

注意该种方法:因为要建K+1层图,数组要开到n*(k+1),点的个数也为n*(k+1)。

 Dijkstra解法:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 int cnt,n,m,k;
 9 const int maxn=1e6+10;
10 const int maxm=1e7;
11 int head[maxn],dis[maxn],vis[maxn];
12 struct edge{
13     int to;
14     int next;
15     int w;
16 }e[maxm];
17 void init()
18 {
19     memset(vis,0,sizeof(vis));
20     memset(head,-1,sizeof(head));
21     memset(dis,inf,sizeof(dis));
22     cnt=0;
23 }
24 void add(int x,int y,int w)
25 {
26     e[cnt].to=y;
27     e[cnt].w=w;
28     e[cnt].next=head[x];
29     head[x]=cnt++;
30 }
31 struct node{
32     int pos;
33     int cost;
34     node(){}
35     node(int pos,int cost):pos(pos),cost(cost){}
36     friend bool operator < (node a,node b)
37     {
38         return a.cost>b.cost;
39     }
40 };
41 void dijkstra(int st)
42 {
43   priority_queue<node>q;
44   dis[st]=0;
45   q.push(node(st,0));
46   while(!q.empty())
47   {
48       node now=q.top();
49       q.pop();
50       if(vis[now.pos])
51             continue;
52       vis[now.pos]=1;
53       for(int i=head[now.pos];i!=-1;i=e[i].next)
54       {
55           int u=e[i].to;
56           if(dis[u]>dis[now.pos]+e[i].w)
57           {
58               dis[u]=dis[now.pos]+e[i].w;
59               q.push(node(u,dis[u]));
60           }
61       }
62   }
63 }
64 int main()
65 {
66     cin>>n>>m>>k;
67     int st,ed;
68     cin>>st>>ed;
69     int a,b,c;
70     init();
71     for(int i=0;i<m;i++)
72     {
73         scanf("%d%d%d",&a,&b,&c);
74         for(int j=0;j<=k;j++)
75         {
76             add(a+j*n,b+j*n,c);
77             add(b+j*n,a+j*n,c);
78             if(j!=k)
79             {
80                 add(a+j*n,b+(j+1)*n,0);
81                 add(b+j*n,a+(j+1)*n,0);
82             }
83         }
84     }
85     dijkstra(st);
86     int ans=214748364;
87     for(int i=0;i<=k;i++)
88     {
89         ans=min(ans,dis[i*n+ed]);
90     }
91     printf("%d\n",ans);
92     return 0;
93 }

spfa解法:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 int cnt,n,m,k;
 9 const int maxn=3e6+10;
10 const int maxm=1e7;
11 int head[maxn],dis[maxn],vis[maxn];
12 struct edge{
13     int to;
14     int next;
15     int w;
16 }e[maxn<<1];
17 void init()
18 {
19     memset(vis,0,sizeof(vis));
20     memset(head,-1,sizeof(head));
21     memset(dis,inf,sizeof(dis));
22     cnt=0;
23 }
24 void add(int x,int y,int w)
25 {
26     e[cnt].to=y;
27     e[cnt].w=w;
28     e[cnt].next=head[x];
29     head[x]=cnt++;
30 }
31 struct node{
32     int pos;
33     int cost;
34     node(){}
35     node(int pos,int cost):pos(pos),cost(cost){}
36     friend bool operator < (node a,node b)
37     {
38         return a.cost>b.cost;
39     }
40 };
41 void dijkstra(int st)
42 {
43   priority_queue<node>q;
44   dis[st]=0;
45   q.push(node(st,0));
46   vis[st]=1;
47   while(!q.empty())
48   {
49       node now=q.top();
50       q.pop();
51       vis[now.pos]=0;
52       for(int i=head[now.pos];i!=-1;i=e[i].next)
53       {
54           int u=e[i].to;
55           if(dis[u]>dis[now.pos]+e[i].w)
56           {
57               dis[u]=dis[now.pos]+e[i].w;
58               if(!vis[u])
59                     vis[u]=1;
60               q.push(node(u,dis[u]));
61           }
62       }
63   }
64 }
65 int main()
66 {
67     int st,ed;
68     scanf("%d%d%d",&n,&m,&k);
69     scanf("%d%d",&st,&ed);
70     int a,b,c;
71     init();
72     for(int i=0;i<m;i++)
73     {
74         scanf("%d%d%d",&a,&b,&c);
75         for(int j=0;j<=k;j++)
76         {
77             add(a+j*n,b+j*n,c);
78             add(b+j*n,a+j*n,c);
79             if(j!=k)
80             {
81                 add(a+j*n,b+(j+1)*n,0);
82                 add(b+j*n,a+(j+1)*n,0);
83             }
84         }
85     }
86     dijkstra(st);
87     int ans=214748364;
88     for(int i=0;i<=k;i++)
89     {
90         ans=min(ans,dis[i*n+ed]);
91     }
92     printf("%d\n",ans);
93     return 0;
94 }

 

posted @ 2018-09-02 23:58  *starry*  阅读(320)  评论(0编辑  收藏  举报