zoukankan      html  css  js  c++  java
  • 【洛谷5304】[GXOI/ZOI2019] 旅行者(二进制分组+最短路)

    点此看题面

    • 给定一张(n)个点(m)条边的有向图和(k)个关键点,求关键点两两之间最短路的最小值。
    • (nle10^5,mle5 imes10^5)

    二进制分组

    一个早就知道的技巧,但一直没有真正写过。

    考虑我们枚举二进制下每一位,把这一位为(0)的分成一组,这一位为(1)的分成一组。

    分别从这两组出发跑多源最短路(显然也可以(Dijkstra)解决),求出到另一组的最短路最小值。

    由于两个不同的点二进制下至少存在一位不同,也就必然在枚举到某一位的时候被分到不同的两组中,所以正确性有了保证。

    代码:(O(nlog^2n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define M 500000
    #define LN 17
    #define LL long long
    #define Pr pair<LL,int>
    #define mp make_pair
    #define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].v=z)
    using namespace std;
    int n,m,k,p[N+5],ee,lnk[N+5];struct edge {int to,nxt,v;}e[M+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	char oc,FI[FS],*FA=FI,*FB=FI;
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }using namespace FastIO;
    LL ans,dis[N+5];int vis[N+5];priority_queue<Pr,vector<Pr>,greater<Pr> > q;I void Dij(CI w,CI g)//多源最短路
    {
    	RI i,k;for(i=1;i<=n;++i) vis[i]=0,p[i]&&(i>>w&1)==g?(q.push(mp(dis[i]=0,i)),0):dis[i]=1e18;//从w位为g的关键点出发
    	W(!q.empty()) if(k=q.top().second,q.pop(),!vis[k]) for(vis[k]=1,//Dijkstra模板
    		i=lnk[k];i;i=e[i].nxt) dis[k]+e[i].v<dis[e[i].to]&&(q.push(mp(dis[e[i].to]=dis[k]+e[i].v,e[i].to)),0);
    	for(i=1;i<=n;++i) p[i]&&(i>>w&1)^g&&(ans=min(ans,dis[i]));//到w位为g^1的关键点的最短路
    }
    int main()
    {
    	RI Tt,i,x,y,z;read(Tt);W(Tt--)
    	{
    		for(read(n,m,k),ans=1e18,ee=0,i=1;i<=n;++i) p[i]=lnk[i]=0;for(i=1;i<=m;++i) read(x,y,z),add(x,y,z);
    		for(i=1;i<=k;++i) read(x),p[x]=1;for(i=0;i<=LN;++i) Dij(i,0),Dij(i,1);printf("%lld
    ",ans);//二进制分组
    	}return 0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Intent的跳转和传值
    Intent传值的学习
    Activity,Window,View之间是什么关系?
    MATCH_PARENT和FILL_PARENT之间的区别?
    Activity的运行过程
    onCreate和onStart谁的开销大?
    SDKManager连不上墙外的网,列表刷新不出来怎么办?
    AndroidEclipse里的视图里想添加SDK Manager但是找不到怎么办?
    出现“Unable to resolve target 'android-XXX'”怎么处理?
    安卓进程的生命周期
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5304.html
Copyright © 2011-2022 走看看