Bzoj 2763: [JLOI2011]飞行路线 dijkstra,堆,最短路,分层图
2763: [JLOI2011]飞行路线
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1728 Solved: 649
[Submit][Status][Discuss]
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
题解:
dijkstra+堆优化
原先用SPFA写过。
原本想练一下dijkstra+堆优化,用了一种先建图再直接跑最短路,就是把相邻两层用双向边去连接,然后每层再连好图。
没想到一写写的我真是2333。。。
这里 Orz 辗转山河弋流歌(好像和Popoqqq,wyfcyx,jkxing大爷们一个机房!!!) 7分钟秒杀和此题差不多的一道题。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 10010 4 #define MAXM 50010 5 #define INF 1e9 6 struct node 7 { 8 int begin,end,value,next; 9 }edge[2*MAXM*11*2]; 10 int cnt,Head[11*MAXN],N,dis[11*MAXN],Heap[11*MAXN],pos[11*MAXN],U[MAXM],V[MAXM],VAL[MAXM],SIZE; 11 void addedge(int bb,int ee,int vv) 12 { 13 edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt; 14 } 15 void addedge1(int bb,int ee,int vv) 16 { 17 addedge(bb,ee,vv);addedge(ee,bb,vv); 18 } 19 int read() 20 { 21 int s=0,fh=1;char ch=getchar(); 22 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 24 return s*fh; 25 } 26 void Push1(int k) 27 { 28 int now=k,root; 29 while(now>1) 30 { 31 root=now/2; 32 if(dis[Heap[root]]<=dis[Heap[now]])return; 33 swap(Heap[root],Heap[now]); 34 swap(pos[Heap[root]],pos[Heap[now]]); 35 now=root; 36 } 37 } 38 void Insert(int k) 39 { 40 Heap[++SIZE]=k;pos[k]=SIZE;Push1(SIZE); 41 } 42 void Pop1(int k) 43 { 44 int now,root=k; 45 pos[Heap[k]]=0;Heap[k]=Heap[SIZE--];if(SIZE>0)pos[Heap[k]]=k; 46 while(root<=SIZE/2) 47 { 48 now=root*2; 49 if(now<SIZE&&dis[Heap[now+1]]<dis[Heap[now]])now++; 50 if(dis[Heap[root]]<=dis[Heap[now]])return; 51 swap(Heap[root],Heap[now]); 52 swap(pos[Heap[root]],pos[Heap[now]]); 53 root=now; 54 } 55 } 56 void dijkstra(int start) 57 { 58 int i,v,u; 59 for(i=1;i<=N;i++)dis[i]=INF;dis[start]=0; 60 for(i=1;i<=N;i++)Insert(i); 61 while(SIZE>0) 62 { 63 u=Heap[1];Pop1(pos[u]); 64 for(i=Head[u];i!=-1;i=edge[i].next) 65 { 66 v=edge[i].end; 67 if(dis[v]>dis[u]+edge[i].value){dis[v]=dis[u]+edge[i].value;Push1(pos[v]);} 68 } 69 } 70 } 71 int main() 72 { 73 int n,m,i,MN,j,k,bb,ee; 74 n=read();m=read();k=read(); 75 bb=read();ee=read();bb++;ee++; 76 for(i=1;i<=m;i++) 77 { 78 U[i]=read();V[i]=read();VAL[i]=read(); 79 U[i]++;V[i]++; 80 } 81 memset(Head,-1,sizeof(Head));cnt=1; 82 N=(k+1)*n; 83 for(i=0;i<=k;i++) 84 { 85 for(j=1;j<=m;j++)addedge1(i*n+U[j],i*n+V[j],VAL[j]); 86 if(i!=k) 87 { 88 for(j=1;j<=m;j++){addedge(i*n+U[j],(i+1)*n+V[j],0);addedge(i*n+V[j],(i+1)*n+U[j],0);} 89 } 90 } 91 dijkstra(bb); 92 MN=INF; 93 for(i=0;i<=k;i++)MN=min(MN,dis[i*n+ee]); 94 printf("%d",MN); 95 fclose(stdin); 96 fclose(stdout); 97 return 0; 98 }