zoukankan      html  css  js  c++  java
  • 飞行路线 HYSBZ

    飞行路线

      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
    ",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
    ",ans);
    93     return 0;
    94 }
  • 相关阅读:
    西门子1200/1500 PLC FC/FB块的区别
    Monaco Editor --Web编辑器 自定义主题、代码提示等
    C# 强制GC垃圾回收
    C# 注册表操作类(查询、修改、删除)
    WinForm重绘Combobox控件无边框样式
    Http-server搭建本地服务
    C# 压缩解压文件夹
    递归获取当前节点和所有父节点
    递归获取当前父节点下的所有子集
    轻量级的通信引擎 StriveEngine
  • 原文地址:https://www.cnblogs.com/1013star/p/9576487.html
Copyright © 2011-2022 走看看