【NOIP 2013 模拟联考 8】最短路

简析

看到 \(0\le k\le10\),\(k\) 非常的小,那么正解可以暴力

预处理的话,我们考虑先把起点 \(s\) 和每一个特殊点做 \(k+1\) 次最短路。

然后暴力枚举 \(O(n!)\) 的顺序,顺序走一次,记录最小值,输出 。

虽说很简单但还是很考验码力。

Warning:当 \(k=0\) 时要特判,否则会出现意想不到的错误。

代码

#include<bits/stdc++.h>
using namespace std;
using LL=long long;
const LL N=5e4+5,M=1e5+5;
struct edge {
	LL to,nxt,w;
} e[M];
LL n,cnt,head[N],dis[N];
bitset<N> vis;
void add(LL u,LL v,LL w) {
	e[++cnt].to=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;
}
priority_queue<pair<LL,LL>> q;
void dijkstra(LL u) {
	q.push(make_pair(0,u)),dis[u]=0;
	while(q.size()) {
		u=q.top().second,q.pop();
		if(vis[u]) {
			continue;
		}
		vis[u]=1;
		for(LL i=head[u],v,w; i; i=e[i].nxt) {
			v=e[i].to,w=e[i].w;
			if(dis[u]+w<dis[v]) {
				dis[v]=dis[u]+w;
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}
void dijkstra(LL u,LL *dis) {
	q.push(make_pair(0,u)),dis[u]=0;
	while(q.size()) {
		u=q.top().second,q.pop();
		if(vis[u]) {
			continue;
		}
		vis[u]=1;
		for(LL i=head[u],v,w; i; i=e[i].nxt) {
			v=e[i].to,w=e[i].w;
			if(dis[u]+w<dis[v]) {
				dis[v]=dis[u]+w;
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}
LL key[15],ge[15][N],a[15];
int main() {
	LL n,m,k,s,t;
	scanf("%lld %lld %lld %lld %lld",&n,&m,&k,&s,&t);
	for(LL i=1,u,v,w; i<=m; i++) {
		scanf("%lld %lld %lld",&u,&v,&w),add(u,v,w);
	}
	for(LL i=1; i<=k; i++) {
		memset(ge[i],0x3f,sizeof(ge[i])),vis=0;
		scanf("%lld",key+i);
		if(key[i]==s||key[i]==t) {
			i--,k--;
			continue;
		}
		dijkstra(key[i],ge[i]),a[i]=i;
	}
	memset(dis,0x3f,sizeof(dis)),vis=0,dijkstra(s);
	LL minn=1e15;
	do {
		LL tmp=dis[key[a[1]]];
		for(LL i=1; i<k; i++) {
			tmp+=ge[a[i]][key[a[i+1]]];
		}
		tmp+=ge[a[k]][t];
		if(!k) {
			tmp=dis[t];
		}
		minn=min(minn,tmp);
	} while(next_permutation(a+1,a+k+1));
	if(minn>=1e12) {
		puts("-1");
		return 0;
	}
	printf("%lld",minn);
	return 0;
}
上一篇:数组主元素(2013考研题)


下一篇:实验4:开源控制器实践——OpenDaylight