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

Luogu P4366 [Code+#4]最短路

时间:2020-01-25 16:51:50      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:tin   ems   return   using   进制   sizeof   www   中间   ack   

Link
直接连边是\(O(n^2)\)的显然不可取。
考虑二进制拆分,对于点\(u\),我们可以只连\(u\rightarrow u\oplus 2^k\)的边,显然在这样建出来的图上跑最短路和在原图上跑最短路是等价的。
不过因为中间可能会经过\(>n\)的点,所以要把点补齐至\([0,2^k)\)

#include<queue>
#include<cstdio>
#include<vector>
#include<cctype>
#include<utility>
#include<cstring>
#include<functional>
#define pi pair<int,int>
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}
using IO::read;
using std::pair;
using std::vector;
using std::greater;
using std::priority_queue;
const int N=131072;
vector<pi>e[N];int dis[N],vis[N];
priority_queue<pi,vector<pi>,greater<pi>>q;
int main()
{
    int k=32-__builtin_clz(read()),n=1<<k,m=read(),C=read(),s,t;
    for(int i=1,u,v,w;i<=m;++i) u=read(),v=read(),w=read(),e[u].emplace_back(v,w);
    for(int i=0;i<n;++i) for(int j=0;j<k;++j) e[i].emplace_back(i^(1<<j),(1<<j)*C);
    s=read(),t=read(),memset(dis,0x7f,sizeof dis),q.emplace(dis[s]=0,s);
    for(int u;!q.empty();)
    {
    u=q.top().second,q.pop();if(vis[u])continue;vis[u]=1;
    for(auto[v,w]:e[u]) if(dis[v]>dis[u]+w) q.emplace(dis[v]=dis[u]+w,v);
    }
    printf("%d",dis[t]);
}

Luogu P4366 [Code+#4]最短路

标签:tin   ems   return   using   进制   sizeof   www   中间   ack   

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12233136.html

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