Bzoj2763 [JLOI2011]飞行路线
Submit: 2651 Solved: 1004
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
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.
Source
最短路。
分层图或DP。
想象把平面图转化成立体结构,每条原有的<u,v>边从一层的u连到同一层或下一层的v,边权为原边权,同时有一条边从一层的u连到下一层的v,边权为0。
起点是第0层的起点城市,终点是第k层的起点城市,跑最短路。
↑这样建边的效果是,在同一层内可以正常求最短路,而每使用一条“免费线路”,状态就会转移到下一层,这样保证最多使用k次免费线路。
——那么问题来了,这种算法确定无误,但是建边消耗内存太大了,怎么解决?
——不知道,我选择和评测机对刚。
卡数据范围反复提交了6次终于AC了。
[其实用DP思想做会更简单,不需要建k层图,只要dis状态开成二维就可以了]
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 using namespace std; 10 const int mxn=120010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int v,nxt; 19 int dis; 20 }e[2400000]; 21 int hd[mxn],mct=0; 22 void add_edge(int u,int v,int dis){ 23 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].dis=dis;hd[u]=mct; 24 return; 25 } 26 int n,m,k; 27 int ans; 28 int dis[mxn]; 29 struct node{ 30 int v,dis; 31 friend bool operator < (node a,node c){return a.dis>c.dis;} 32 }; 33 priority_queue<node>q; 34 int Dij(int st,int ed){ 35 memset(dis,0x3f,sizeof dis); 36 dis[st]=0; 37 q.push((node){st,0}); 38 int i,j; 39 while(!q.empty()){ 40 node now=q.top();q.pop(); 41 if(dis[now.v]<now.dis)continue; 42 int u=now.v; 43 for(i=hd[u];i;i=e[i].nxt){ 44 int v=e[i].v; 45 if(dis[v]>dis[u]+e[i].dis){ 46 dis[v]=dis[u]+e[i].dis; 47 q.push((node){v,dis[v]}); 48 } 49 } 50 } 51 return dis[ed+k*n]; 52 } 53 int main(){ 54 n=read();m=read();k=read(); 55 int i,j; 56 int s=read()+1,t=read()+1; 57 int u,v,d; 58 for(i=1;i<=m;i++){ 59 u=read()+1;v=read()+1;d=read(); 60 for(j=0;j<=k;j++){ 61 add_edge(u+j*n,v+j*n,d); 62 add_edge(v+j*n,u+j*n,d); 63 if(j<k){ 64 add_edge(u+j*n,v+j*n+n,0); 65 add_edge(v+j*n,u+j*n+n,0); 66 } 67 } 68 } 69 int ans=Dij(s,t); 70 // for(i=1;i<=n*k+n;i++)printf("%d\n",dis[i]); 71 printf("%d\n",ans); 72 return 0; 73 }
本文为博主原创文章,转载请注明出处。