码迷,mamicode.com
首页 > 其他好文 > 详细

最短路——分层图

时间:2019-10-06 20:36:15      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:win   print   电话线   main   inf   activity   作者   使用   ref   

https://www.luogu.org/problem/P1948

LuoguP1948 电话线

K次免费机会-->每个点(i)拆成(i,k),表示使用了k次免费机会后的i;

于是就将平常的一张图(二维)转换为立体图(三维),但实现上还是二维的

每层跟平常一样建边,然后再在两层之间建图作为联系,即免费边。

最后看每层的(n,k)点的dis(使用了k次机会后到n的花费);

dis[v]>dis[u]+val[i]根据题改为dis[v]>max(dis[u],val[i]);

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=1e7+10,INF=1e9;
int n,p,k;
int head[N],nex[M*2],to[M*2],val[M*2],tot;
void build(int u,int v,int w){tot++;nex[tot]=head[u];to[tot]=v;val[tot]=w;head[u]=tot;}
bool vis[N];
int dis[N];
priority_queue<pair<int,int> >q;
void spfa()
{
    for(int i=1;i<=n*(k+1);i++)dis[i]=INF;
    q.push(make_pair(-0,1));
    dis[1]=0;
    while(!q.empty())
    {
        int u=q.top().second;q.pop();
        if(vis[u])continue;vis[u]=1;
        for(int i=head[u];i;i=nex[i])
        {
            int v=to[i],w=max(dis[u],val[i]);
            if(dis[v]>w)
            {
                dis[v]=w;
                q.push(make_pair(-w,v));
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&p,&k);
    for(int u,v,w,i=1;i<=p;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        for(int j=0;j<=k;j++)
        {
            build(u+j*n,v+j*n,w);
            build(v+j*n,u+j*n,w);
        }
        for(int j=0;j<k;j++)
        {
            build(u+j*n,v+(j+1)*n,0);
            build(v+j*n,u+(j+1)*n,0);
        }
    }
    spfa();
    int ans=INF;
    for(int i=0;i<=k;i++)
    {
        ans=min(ans,dis[n+i*n]);
    }
    if(ans!=INF)printf("%d",ans);
    else printf("-1");
}

作者:yfxJ518
链接:https://www.acwing.com/activity/content/code/content/124992/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

最短路——分层图

标签:win   print   电话线   main   inf   activity   作者   使用   ref   

原文地址:https://www.cnblogs.com/fengJ518/p/11628114.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!