普通快乐「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();
}

原文地址:https://www.cnblogs.com/ilverene/p/11812998.html