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
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
题解:
分层图+dijkstra+堆优化
直接将相邻两层相连,每层内也要连。然后从1开始跑最短路。最后把每层的最后一个的值取个最小即可。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
#define MAXM 50010
#define INF 1e9
struct node
{
int end,value,next;
}edge[**MAXM];
int cnt,Head[*MAXN],N,dis[*MAXN],Heap[*MAXN],pos[*MAXN],SIZE,U[MAXM],V[MAXM],VAL[MAXM];
void addedge(int bb,int ee,int vv)
{
edge[++cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
}
void addedge1(int bb,int ee,int vv)
{
addedge(bb,ee,vv);addedge(ee,bb,vv);
}
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void Push1(int k)
{
int now=k,root;
while(now>)
{
root=now/;
if(dis[Heap[root]]<=dis[Heap[now]])return;
swap(Heap[root],Heap[now]);
swap(pos[Heap[root]],pos[Heap[now]]);
now=root;
}
}
void Insert(int k)
{
Heap[++SIZE]=k;pos[k]=SIZE;Push1(SIZE);
}
void Pop1(int k)
{
int now,root=k;
pos[Heap[k]]=;Heap[k]=Heap[SIZE--];if(SIZE>)pos[Heap[k]]=k;
while(root<=SIZE/)
{
now=root*;
if(now<SIZE&&dis[Heap[now+]]<dis[Heap[now]])now++;
if(dis[Heap[root]]<=dis[Heap[now]])return;
swap(Heap[root],Heap[now]);
swap(pos[Heap[root]],pos[Heap[now]]);
root=now;
}
}
void dijkstra(int start)
{
int i,v,u;
for(i=;i<=N;i++)dis[i]=INF;dis[start]=;
for(i=;i<=N;i++)Insert(i);
while(SIZE>)
{
u=Heap[];Pop1(pos[u]);
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(dis[v]>dis[u]+edge[i].value){dis[v]=dis[u]+edge[i].value;Push1(pos[v]);}
}
}
}
int main()
{
int n,m,i,MN,j,k;
n=read();m=read();k=read();
for(i=;i<=m;i++)
{
U[i]=read();V[i]=read();VAL[i]=read();
}
memset(Head,-,sizeof(Head));cnt=;
N=(k+)*n;
for(i=;i<=k;i++)
{
for(j=;j<=m;j++)addedge1(i*n+U[j],i*n+V[j],VAL[j]);
if(i!=k)
{
for(j=;j<=m;j++){addedge(i*n+U[j],(i+)*n+V[j],);addedge(i*n+V[j],(i+)*n+U[j],);}
}
}
dijkstra();
MN=INF;
for(i=;i<=k;i++)MN=min(MN,dis[i*n+n]);
printf("%d",MN);
fclose(stdin);
fclose(stdout);
return ;
}