【BZOJ1579】Revamping Trails(分层图,最短路,堆)

题意:每天,农夫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的时间尽量少.

N<=10000

思路:裂点建分层图后跑最短路

C++ dijksta+堆板子

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<map>
 8 #include<set>
 9 #include<queue>
10 #include<vector>
11 using namespace std;
12 typedef long long ll;
13 typedef unsigned int uint;
14 typedef unsigned long long ull;
15 typedef pair<int,int> PII;
16 typedef vector<int> VI;
17 #define fi first
18 #define se second
19 #define MP make_pair
20 #define N   11000
21 #define M   51000
22 #define eps 1e-8
23 #define pi  acos(-1)
24 #define oo  1e9
25 priority_queue<pair<int,int> > q;
26 int num[N][21],head[N*21],vet[M*90],len[M*90],nxt[M*90],
27     dis[N*21],vis[N*21],tot;
28  
29 int add(int a,int b,int c)
30 {
31     nxt[++tot]=head[a];
32     vet[tot]=b;
33     len[tot]=c;
34     head[a]=tot;
35 }
36  
37 int main()
38 {
39     int n,m,K;
40     scanf("%d%d%d",&n,&m,&K);
41     int s=0;
42     for(int i=1;i<=n;i++)
43      for(int j=0;j<=K;j++) num[i][j]=++s;
44     for(int i=1;i<=m;i++)
45     {
46         int x,y,z;
47         scanf("%d%d%d",&x,&y,&z);
48         for(int j=0;j<K;j++)
49         {
50             add(num[x][j],num[y][j+1],0);
51             add(num[y][j],num[x][j+1],0);
52         }
53         for(int j=0;j<=K;j++)
54         {
55             add(num[x][j],num[y][j],z);
56             add(num[y][j],num[x][j],z);
57         }   
58     }
59     memset(vis,0,sizeof(vis));
60     memset(dis,0x3f,sizeof(dis));
61     q.push(MP(0,num[1][0])); dis[num[1][0]]=0;
62     while(!q.empty())
63     {
64         int u=q.top().se;
65         q.pop();
66         if(vis[u]) continue;
67         vis[u]=1;
68         int e=head[u];
69         while(e)
70         {
71             int v=vet[e];
72             if(dis[u]+len[e]<dis[v])
73             {
74                 dis[v]=dis[u]+len[e];
75                 q.push(MP(-dis[v],v));
76             }
77             e=nxt[e];
78         }
79     }
80     int ans=oo;
81     for(int i=0;i<=K;i++) ans=min(ans,dis[num[n][i]]);
82     printf("%d\n",ans);
83     return 0;
84 }

 

posted on 2018-10-16 18:37  myx12345  阅读(127)  评论(0编辑  收藏  举报

导航