zoukankan      html  css  js  c++  java
  • 【LOJ3087】「GXOI / GZOI2019」旅行者

    题意

    给定一个 (n) 个点 (m) 条边的的有向图,给出 (k) 个关键点,求关键点两两最短路的最小值。

    (nle 10^5, mle 5cdot 10^5).

    题解

    二进制分组。对于每一位,将编号当前位为 (0) 的点做源点/汇点, 当前位为 (1) 的点做汇点/源点,然后跑最短路。

    复杂度 (O(nlog ^2 n)) .

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    namespace io {
    	const int SIZE=(1<<21)+1;
    	char ibuf[SIZE],*iS,*iT,c; int qr;
    #define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    	inline int gi (){
    		int x=0;
    		for(c=gc();c<'0'||c>'9';c=gc());
    		for(;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15); return x;
    	}
    } using io::gi;
    const int N=1e5+5,M=5e5+5;
    typedef long long ll;
    int head[N],nxt[M],to[M],wei[M],n,m,k,key[N];
    #define pr pair<int,int>
    priority_queue< pr,vector<pr>,greater<pr> > q; 
    ll dis[N];
    void addedge(int u, int v, int w, int now) {
    	nxt[now]=head[u], head[u]=now, to[now]=v, wei[now]=w;
    }
    int main()
    {
    #ifdef lc
    	freopen("a.in","r",stdin);
    #endif
    	int T=gi();
    	while(T--)
    	{
    		memset(head,0,sizeof(head));
    		n=gi(),m=gi(),k=gi();
    		for(int i=1;i<=m;++i)
    		{
    			int u=gi(),v=gi(),w=gi();
    			addedge(u,v,w,i);
    		}
    		for(int i=1;i<=k;++i) key[i]=gi();
    		ll ans=1ll<<60;
    		for(int i=0;i<17;++i)
    		{
    			memset(dis,0x3f,sizeof(dis));
    			for(int j=1;j<=k;++j)
    				if(key[j]&(1<<i))
    				{
    					dis[key[j]]=0;
    					q.push(make_pair(0,key[j]));
    				}
    			while(!q.empty())
    			{
    				ll tmp=q.top().first;
    				int u=q.top().second; q.pop();
    				if(dis[u]!=tmp)continue;
    				for(int e=head[u];e;e=nxt[e])
    					if(dis[to[e]]>dis[u]+wei[e])
    					{
    						dis[to[e]]=dis[u]+wei[e];
    						q.push(make_pair(dis[to[e]],to[e]));
    					}
    			}
    			for(int j=1;j<=k;++j) if(!(key[j]&(1<<i))) ans=min(ans,dis[key[j]]); 
    		}
    		for(int i=0;i<17;++i)
    		{
    			memset(dis,0x3f,sizeof(dis));
    			for(int j=1;j<=k;++j)
    				if(!(key[j]&(1<<i)))
    				{
    					dis[key[j]]=0;
    					q.push(make_pair(0,key[j]));
    				}
    			while(!q.empty())
    			{
    				ll tmp=q.top().first;
    				int u=q.top().second; q.pop();
    				if(dis[u]!=tmp)continue;
    				for(int e=head[u];e;e=nxt[e])
    					if(dis[to[e]]>dis[u]+wei[e])
    					{
    						dis[to[e]]=dis[u]+wei[e];
    						q.push(make_pair(dis[to[e]],to[e]));
    					}
    			}
    			for(int j=1;j<=k;++j) if(key[j]&(1<<i)) ans=min(ans,dis[key[j]]); 
    		}
    		printf("%lld
    ",ans);
    	}
    }
    
  • 相关阅读:
    正则表达式验证银行卡号
    正则表达式验证银行卡号
    正则表达式验证手机号
    正则表达式验证手机号
    好用的手机浏览器
    jmeter(三)跨线程组调用token
    jmeter(二)ant报告模板下载与使用
    1-5JSON数据解析
    1-3HTTP协议基础
    1-2接口测试概述
  • 原文地址:https://www.cnblogs.com/farway17/p/10747216.html
Copyright © 2011-2022 走看看