您的位置:首页 > Web前端

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

2017-08-29 21:19 435 查看

【算法】分层图最短路

【题解】

考虑k层一模一样的图,然后每个夹层都在每条边的位置新加从上一层跨越到下一层的边权为0的边,这样至多选择k条边置为0。

然后考虑方便的写法。

SPFA

第一次SPFA计算常规最短路(顶层)。

之后k次SPFA,松弛操作加上可以从上一层节点直接获取最短路(即相当于省一条边)

这样可以保证一次SPFA最多只有一条边省略,因为你要么从上一层前一个点下来,其实是获取上一层前一个点的最短路。

要么从前面一个点过来,其实是获取本层的最短路,本层最短路最多从上面下来一次。

因为只与上一层有关,开滚动数组。

SPFA记得SLF优化,不然较慢!

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct edge{int v,w,from;}e[maxn];
struct cyc{
int x,k,d;
bool operator < (const cyc &a)const{
return d>a.d;
}
};
priority_queue<cyc>q;
int n,m,first[maxn],tot,d[maxn][30],kind;

void insert(int u,int v,int w){
tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].w=w;e[tot].from=first[v];first[v]=tot;
}
int dijkstra(){
q.push((cyc){1,0,0});
memset(d,0x3f,sizeof(d));
d[1][0]=0;
while(!q.empty()){
cyc x=q.top();q.pop();
if(x.d!=d[x.x][x.k])continue;
if(x.x==n)return x.d;
for(int i=first[x.x];i;i=e[i].from){
if(d[e[i].v][x.k]>d[x.x][x.k]+e[i].w){d[e[i].v][x.k]=d[x.x][x.k]+e[i].w;q.push((cyc){e[i].v,x.k,d[e[i].v][x.k]});}
if(x.k<kind&&d[e[i].v][x.k+1]>d[x.x][x.k]){d[e[i].v][x.k+1]=d[x.x][x.k];q.push((cyc){e[i].v,x.k+1,d[e[i].v][x.k+1]});}
}
}
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&kind);
int u,v,w;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);
}
printf("%d",dijkstra());
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: