1579: [Usaco2009 Feb]Revamping Trails 道路升级
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1573 Solved: 428
[Submit][Status][Discuss]
Description
每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走到P1_i 他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 <= K <= 20)条路经,将它们所须时间减为0.帮助FJ选择哪些路经需要更新使得从1到N的时间尽量少.
Input
* 第一行: 三个空格分开的数: N, M, 和 K * 第2..M+1行: 第i+1行有三个空格分开的数:P1_i, P2_i, 和 T_i
Output
* 第一行: 更新最多K条路经后的最短路经长度.
Sample Input
4 4 1
1 2 10
2 4 10
1 3 1
3 4 100
1 2 10
2 4 10
1 3 1
3 4 100
Sample Output
1
HINT
K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位. N<=10000
Source
题解:
分层图+dijkstra+堆优化
直接将相邻两层相连,每层内也要连。然后从1开始跑最短路。最后把每层的最后一个的值取个最小即可。
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 end,value,next; 9 }edge[21*4*MAXM]; 10 int cnt,Head[21*MAXN],N,dis[21*MAXN],Heap[21*MAXN],pos[21*MAXN],SIZE,U[MAXM],V[MAXM],VAL[MAXM]; 11 void addedge(int bb,int ee,int vv) 12 { 13 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; 74 n=read();m=read();k=read(); 75 for(i=1;i<=m;i++) 76 { 77 U[i]=read();V[i]=read();VAL[i]=read(); 78 } 79 memset(Head,-1,sizeof(Head));cnt=1; 80 N=(k+1)*n; 81 for(i=0;i<=k;i++) 82 { 83 for(j=1;j<=m;j++)addedge1(i*n+U[j],i*n+V[j],VAL[j]); 84 if(i!=k) 85 { 86 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);} 87 } 88 } 89 dijkstra(1); 90 MN=INF; 91 for(i=0;i<=k;i++)MN=min(MN,dis[i*n+n]); 92 printf("%d",MN); 93 fclose(stdin); 94 fclose(stdout); 95 return 0; 96 }