ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Luogu P5304 [GXOI/GZOI2019]旅行者

2020-06-06 10:06:27  阅读:297  来源: 互联网

标签:std int Luogu i64 read GZOI2019 include P5304 dis


Link
二进制分组。每次选定一个二进制位,把特殊点按编号在这一位上的状态分为两半,跑两遍dij求出这两半之间的最短路。

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<functional>
using i64=long long;
using pi=std::pair<int,int>;
const int N=100007;const i64 inf=1ll<<60;
char ibuf[1<<25],*iS=ibuf;int n,is[N];i64 ans,dis[N];std::vector<pi>e[N];std::priority_queue<pi,std::vector<pi>,std::greater<pi>>q;
int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
void solve(int d,int t)
{
    memset(dis+1,0x3f,8*n);
    for(int i=1;i<=n;++i) if(is[i]&&(i>>d&1)==t) q.emplace(dis[i]=0,i);
    while(!q.empty())
    {
	int u=q.top().second;i64 d=q.top().first;q.pop();
	if(d==dis[u]) for(auto[v,w]:e[u]) if(dis[v]>dis[u]+w) q.emplace(dis[v]=dis[u]+w,v);
    }
    for(int i=1;i<=n;++i) if(is[i]&&(~i>>d&1)==t) ans=std::min(ans,dis[i]);
}
void solve()
{
    n=read(),ans=inf,memset(is+1,0,4*n);
    int m=read(),k=read();
    for(int i=1;i<=n;++i) e[i].clear();
    for(int u,v,w;m;--m) u=read(),v=read(),w=read(),e[u].emplace_back(v,w);
    while(k--) is[read()]=1;
    for(int k=0;k<17;++k) solve(k,0),solve(k,1);
    printf("%lld\n",ans);
}
int main()
{
    fread(ibuf,1,1<<25,stdin);
    for(int t=read();t;--t) solve();
}

标签:std,int,Luogu,i64,read,GZOI2019,include,P5304,dis
来源: https://www.cnblogs.com/cjoierShiina-Mashiro/p/13053653.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有