首页 > 代码库 > 分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线

分层图+最短路算法 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 KSD10 {11     int v,len,next;12 }e[M<<1];13 int head[N],cnt;14 struct Lux15 {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  

 

 

分层图+最短路算法 BZOJ 2763: [JLOI2011]飞行路线