1135. 新年好 (Dijkstra,dfs枚举)

1135. 新年好 - AcWing题库

重庆城里有 n 个车站,m 条 双向 公路连接其中的某些车站。

每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。

在一条路径上花费的时间等于路径上所有公路需要的时间之和。

佳佳的家在车站 11,他有五个亲戚,分别住在车站 a,b,c,d,e

过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。

怎样走,才需要最少的时间?

输入格式

第一行:包含两个整数 n,m,分别表示车站数目和公路数目。

第二行:包含五个整数 a,b,c,d,e,分别表示五个亲戚所在车站编号。

以下 m 行,每行三个整数 x,y,t,表示公路连接的两个车站编号和时间。

输出格式

输出仅一行,包含一个整数 T,表示最少的总时间。

数据范围

1≤n≤50000
1≤m≤105
1<a,b,c,d,e≤n
1≤x,y≤n
1≤t≤100

输入样例:
6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7
输出样例:
21

解析: 

这道题很容易想到用枚举的方式将所有的路线情况都枚举一遍,然后用最短路算法求出路线上两个点之间的最短距离,将路线上的所有距离相加即可得到最小距离,再从这些最小距离中选出最优解即可。但这里 5!中情况,如果直接按照上述说法进行处理则会超时,5!*o(mlogn)=x*1e7的时间,基本上会超时。

所以这里我们改变一下算法的顺序,我们先将 1,a,b,c,d,e,都先跑一遍最短路,然后再枚举路线,这样时间复杂度就变成了 5!+o(mlogn),这样就可以过了。

注意,这道题不能使用 spfa 算法,题目数据卡常数,所以使用 Dijkstra 算法跑最短路。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
using namespace std;
typedef pair<double, int > PDI;
typedef pair<int, int> PII;
const int N = 5e4+5, M = 2e5 + 5;
int n, m;
int su[10];
int h[N], e[M], w[M], ne[M], idx;
int d[6][N], vis[N];

void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void Dijkstra(int start, int d[]) {
	memset(vis, 0, sizeof vis);
	d[start] = 0;
	priority_queue<PII, vector<PII>, greater<PII>>q;
	q.push({ d[start],start });
	while (!q.empty()) {
		int t = q.top().second;
		q.pop();
		if (vis[t])continue;
		vis[t] = 1;
		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (d[j] > d[t] + w[i]) {
				d[j] = d[t] + w[i];
				q.push({ d[j],j });
			}
		}
	}
}

int dfs(int u,int num,int dist) {
	if (num == 6) {
		return dist;
	}
	int ret = 0x3f3f3f3f;
	for (int i = 1; i <= 5; i++) {
		if (vis[i] == 0) {
			vis[i] = 1;
			ret = min(ret, dfs(i, num + 1, dist + d[u][su[i]]));
			vis[i] = 0;
		}
	}
	return ret;
}

int main() {
	cin >> n >> m;
	for (int i = 1; i <= 5;i++) {
		scanf("%d", &su[i]);
	}
	su[0] = 1;
	memset(h, -1, sizeof h);
	for (int i = 1,a,b,c; i <= m; i++) {
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c);
		add(b, a, c);
	}
	memset(d, 0x3f3f3f3f, sizeof d);
	for (int i = 0; i <= 5; i++) {
		Dijkstra(su[i], d[i]);
	}

	vis[0] = 1;
	for (int i = 1; i <= 5; i++)vis[i] = 0;
	cout << dfs(0, 1, 0) << endl;

	return 0;
}

posted @ 2024-01-09 16:28  Landnig_on_Mars  阅读(2)  评论(0编辑  收藏  举报  来源