Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

1579: [Usaco2009 Feb]Revamping Trails 道路升级

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 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

Sample Output

1

HINT

 

K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位. N<=10000

 

Source

Gold

题解:

分层图+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 }

 

posted @ 2016-03-28 00:54  微弱的世界  阅读(309)  评论(0编辑  收藏  举报