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

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

 
思路:这个题目比较简单,直接列点,把状态表示成二维,然后用最短路径算法求出。 
注意本题卡spfa,用可以堆优化的dijsktra来做。   
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int const N=100000+3;
 4 int const M=20+1;
 5 long long  const inf=1e12;
 6 #define ll long long
 7 int vis[N][M],n,m,K,h[N],cnt;
 8 ll d[N][M];
 9 struct edge {
10     int to,nt,w;
11 } e[N<<2];
12 struct node {
13     int x,y;
14     ll d;
15     bool operator < (const node &rhs) const {
16         return d>rhs.d;
17     }
18 };
19 priority_queue<node> q;
20 void add(int a,int b,int c) {
21     e[++cnt].to=b;
22     e[cnt].w=c;
23     e[cnt].nt=h[a];
24     h[a]=cnt;
25 }
26 ll  dijsktra() {
27     for(int i=1; i<=n; i++)
28         for(int j=0; j<=K; j++)
29             d[i][j]=inf;
30     d[1][0]=0;
31     node t=(node){1,0,0};
32     q.push(t);
33     while (!q.empty()) {
34         int x=q.top().x;
35         int y=q.top().y;
36         q.pop();
37         if(vis[x][y]) continue;
38         vis[x][y]=1;
39         for(int i=h[x]; i; i=e[i].nt) {
40             int v=e[i].to;
41             if(d[v][y]>d[x][y]+e[i].w && !vis[v][y] ) {
42                 d[v][y]=d[x][y]+e[i].w;
43                 node t=(node){v,y,d[v][y]};
44                 q.push(t);
45             }
46             if(y+1<=K && d[v][y+1]>d[x][y] && !vis[v][y+1]) {
47                 d[v][y+1]=d[x][y];
48                 node t=(node){v,y+1,d[v][y+1]};
49                 q.push(t);  
50             }
51         }
52     }
53     ll  ans=inf;
54     for(int i=0; i<=K; i++)
55         ans=min(ans,d[n][i]);
56     return ans;
57 }
58 int main() {
59     scanf("%d%d%d",&n,&m,&K);
60     while (m--) {
61         int x,y,z;
62         scanf("%d%d%d",&x,&y,&z);
63         add(x,y,z);
64         add(y,x,z);
65     }
66     printf("%lld\n",dijsktra());
67     return 0;
68 }
View Code

 

posted @ 2019-04-24 17:21  zjxxcn  阅读(146)  评论(0编辑  收藏  举报