• 普通快乐「CSP多校联考 2019」


    题意

    给定一个连通图,上面有若干标记点,求这些标记点之间的最短路。保证没有重边和自环。


    思路

    二进制分组一下,按照二进制位将标记点分开。每一组跑一次多源最短路(伪)(其实就是将多个点扔进优先队列跑dijk)。

    (数据有点水,分成三组都能过)

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
        template<typename T>inline void read (T &x) {
            x=0;T f=1;char c=getchar();
            for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
            for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
            x*=f;
        }
    
        template<typename T>inline void write (T x) {
            if (x<0) putchar('-'),x*=-1;
            if (x>=10) write(x/10);
            putchar(x%10+'0');
        }
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	
    	const int N=100100;
    	const int INF=2147483647;
    	
    	int n,m,k,ans=INF;
    	int cnt;
    	int head[N];
    	struct node {
    		int to,next,val;
    	} edge[N<<2];
    	int toad[N];
    	int dis[N],vis[N];
    	struct tst {
    		int first,v;
    		tst () : first(0),v(0) {}
    		tst (int _f,int _v) : first(_f),v(_v) {}
    		bool operator < (const tst x) const {
    			return v>x.v;
    		}
    	};
    	priority_queue<tst> q;
    	
    	inline void add (int a,int b,int c) {
    		edge[++cnt].to=b,edge[cnt].val=c,edge[cnt].next=head[a],head[a]=cnt;
    	}
    	void dijkstra (int x) {
    		for (register int i=1; i<=n; ++i) dis[i]=INF,vis[i]=0;
    		for (register int i=1; i<=k; ++i) if (toad[i]&(1<<x)) q.push(tst(toad[i],0)),dis[toad[i]]=0,vis[toad[i]]=1;
    		while (!q.empty()) {
    			tst now=q.top();q.pop();
    			for (register int i=head[now.first]; i; i=edge[i].next) {
    				int to=edge[i].to;
    				if (dis[to]>dis[now.first]+edge[i].val) {
    					dis[to]=dis[now.first]+edge[i].val;
    					if (!vis[to]) vis[to]=1,q.push(tst(to,dis[to]));
    				}
    			}
    		}
    		for (register int i=1; i<=k; ++i) if (!(toad[i]&(1<<x))) ans=min(ans,dis[toad[i]]);
    	}
    
    	inline void MAIN () {
    		read(n),read(m),read(k);
    		for (register int i=1,x,y,z; i<=m; ++i) {
    			read(x),read(y),read(z);
    			add(x,y,z),add(y,x,z);
    		}
    		for (register int i=1; i<=k; ++i) read(toad[i]);
    		for (register int i=0; i<=16; ++i) dijkstra(i);
    		write(ans);
    	}
    
    }
    
    int main () {
    //    freopen(".in","r",stdin);
    //    freopen(".out","w",stdout);
        Project::MAIN();
    }
    
    
  • 相关阅读:
    【BZOJ3784】树上的路径 点分治序+ST表
    【BZOJ3698】XWW的难题 有上下界的最大流
    【BZOJ2006】[NOI2010]超级钢琴 ST表+堆
    【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
    【BZOJ2724】[Violet 6]蒲公英 分块+二分
    【BZOJ3697】采药人的路径 点分治
    【BZOJ4026】dC Loves Number Theory 分解质因数+主席树
    【BZOJ3510】首都 LCT维护子树信息+启发式合并
    Python Web学习笔记之socket编程
    Python Web学习笔记之socket套接字
  • 原文地址:https://www.cnblogs.com/ilverene/p/11812998.html
Copyright © 2020-2023  润新知