分层图+最短路算法 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\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  

 

 

posted @ 2016-10-02 12:26  csgc0131123  阅读(880)  评论(0编辑  收藏  举报