EOJ:Revamping Trails
Revamping Trails
Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submits: 107 | Accepted: 22 |
Description
Farmer John dutifully checks on the cows every day. He traverses some of the M (1 <= M <= 50,000) trails conveniently numbered 1..M from pasture 1 all the way out to pasture N (a journey which is always possible for trail maps given in the test data). The N (1 <= N <= 10,000) pastures conveniently numbered 1..N on Farmer John's farm are currently connected by bidirectional dirt trails. Each trail i connects pastures P1_i and P2_i (1 <= P1_i <= N; 1 <= P2_i <= N) and requires T_i (1 <= T_i <= 1,000,000) units of time to traverse.
He wants to revamp some of the trails on his farm to save time on his long journey. Specifically, he will choose K (1 <= K <= 20) trails to turn into highways, which will effectively reduce the trail's traversal time to 0. Help FJ decide which trails to revamp to minimize the resulting time of getting from pasture 1 to N.
He wants to revamp some of the trails on his farm to save time on his long journey. Specifically, he will choose K (1 <= K <= 20) trails to turn into highways, which will effectively reduce the trail's traversal time to 0. Help FJ decide which trails to revamp to minimize the resulting time of getting from pasture 1 to N.
Input
* Line 1: Three space-separated integers: N, M, and K
* Lines 2..M+1: Line i+1 describes trail i with three space-separated integers: P1_i, P2_i, and T_i
* Lines 2..M+1: Line i+1 describes trail i with three space-separated integers: P1_i, P2_i, and T_i
Output
* Line 1: The length of the shortest path after revamping no more than K edges
Sample Input
4 4 11 2 102 4 101 3 13 4 100
Sample Output
1
Hint
K is 1; revamp trail 3->4 to take time 0 instead of 100. The new shortest path is 1->3->4, total traversal time now 1
_____________________________________________________________________________________________________________
题解:
也可以算是动归吧,DIJ就是动归的思想
分层图最短路,拆点,将每个点拆成k+1个点,相当于将原图拆成K+1幅图
若原图中(U,V)有一条边,权值为Z,则在拆分后的图中(Ui,Vi)都有权值为Z的边,且(Ui,Vi+1)有条权值为0的边。如下图,点5,6,7,8分别为1,2,3,4拆出来的点,点1向6,8连两条权值为0的边,其他点依次类推。
每经过一层,就相当于使用了一张优惠券。答案即为起点到每层的终点的最短路中最小的一个,因为优惠券可能用不完。
堆优化的DIJ最短路算法。
代码
1 #include<stdio.h>
2 #define maxn 10005
3 #define maxm 50005
4 #define mmax 999999999
5 int head[maxn*2],node[maxm*3],weigh[maxm*3],next[maxm*3],loc[maxn*23];
6 long long dist[maxn*23];
7 int heap[maxn*23],flag[maxn*23];
8 int n,m,k,i,t,j,a,b,c,u,v,len,nown;
9 long long ans;
10 void cedge(int a,int b,int c ,int d)
11 {
12 node[d]=b;
13 weigh[d]=c;
14 next[d]=head[a];
15 head[a]=d;
16 }
17 void update(int r)
18 {
19 int q=loc[r],p=q>>1;
20 while (p&&dist[heap[p]]>dist[r])
21 {
22 loc[heap[p]]=q;
23 heap[q]=heap[p];
24 q=p;p=q>>1;
25 }
26 heap[q]=r;
27 loc[r]=q;
28 }
29 int getmin()
30 {
31 int ret=heap[1],p=1,q=2,r=heap[len--];
32 while (q<=len)
33 {
34 if (q<len&&dist[heap[q+1]]<dist[heap[q]]) q++;
35 if (dist[heap[q]]<dist[r])
36 {
37 loc[heap[q]]=p;
38 heap[p]=heap[q];
39 p=q;
40 q=p<<1;
41 }
42 else break;
43 }
44 heap[p]=r;
45 loc[r]=p;
46 return ret;
47 }
48 void dijkstra()
49 {
50 nown=n*(k+1);
51 for (i=1;i<=n*(k+1);i++)
52 {
53 dist[i]=mmax;
54 flag[i]=0;
55 loc[i]=0;
56 }
57 dist[1]=0;
58 heap[1]=1;
59 loc[1]=1;
60 len=1;
61 while (flag[nown]==0)
62 {
63 u=getmin();
64 flag[u]=1;
65 t=(u-1)/n;
66 j=head[u-t*n];
67 do
68 {
69 v=node[j]+n*t;
70 if (flag[v]==0&&dist[v]>dist[u]+weigh[j])
71 {
72 dist[v]=dist[u]+weigh[j];
73 if (loc[v]==0)
74 {
75 heap[++len]=v;
76 loc[v]=len;
77 }
78 update(v);
79 }
80 if (t+1<=k)
81 if (flag[v]==0&&dist[v+n]>dist[u])
82 {
83 dist[v+n]=dist[u];
84 if (loc[v+n]==0)
85 {
86 heap[++len]=v+n;
87 loc[v+n]=len;
88 }
89 update(v+n);
90 }
91 j=next[j];
92 }
93 while (j!=0);
94 }
95 }
96 int main()
97 {
98 scanf("%d%d%d",&n,&m,&k);
99 t=0;
100 for (i=1;i<=m;i++)
101 {
102 scanf("%d%d%d",&a,&b,&c);
103 t++;
104 cedge(a,b,c,t);
105 t++;
106 cedge(b,a,c,t);
107 }
108 dijkstra();
109 ans=mmax;
110 for (i=1;i<=k+1;i++)
111 if (ans>dist[n*i])
112 ans=dist[n*i];
113 printf("%lld\n",ans);
114 return 0;
115 }
116