【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 }
null