zoukankan      html  css  js  c++  java
  • 分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线

    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
    ",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
    ",ans);
    110     return 0;
    111 }
    112  
  • 相关阅读:
    PHP小案例
    PHP函数
    PHP基础语法
    PHP基础知识
    tp5.1前台模板的系统变量输出
    PHP常用方法很有意义的博客网址
    VS 2010(2005)Unicode使用cximage库Load函数问题
    坑爹的CFile::Remove
    固定CDockablePane的一些小技巧
    (转)理解Bitblt、StretchBlt与SetDIBitsToDevice、StretchDibits
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5900825.html
Copyright © 2011-2022 走看看