[CQOI2005] 新年好
重庆城里有 nnn 个车站,mmm 条双向公路连接其中的某些车站。每两个车站最多用一条公路连接,从任何一个车站出发都可以经过一条或者多条公路到达其他车站,但不同的路径需要花费的时间可能不同。在一条路径上花费的时间等于路径上所有公路需要的时间之和。
佳佳的家在车站 111,他有五个亲戚,分别住在车站 a,b,c,d,ea,b,c,d,ea,b,c,d,e。过年了,他需要从自己的家出发,拜访每个亲戚(顺序任意),给他们送去节日的祝福。怎样走,才需要最少的时间?
输入格式
第一行:n,mn,mn,m,分别为车站数目和公路的数目。
第二行:a,b,c,d,ea,b,c,d,ea,b,c,d,e,分别为五个亲戚所在车站编号。
以下 mmm 行,每行三个整数 x,y,tx,y,tx,y,t,为公路连接的两个车站编号和时间。
输出格式
仅一行,包含一个整数 TTT,为最少的总时间。保证 T≤109T\le 10^9T≤109。
样例输入 #1
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
样例输出 #1
21
对于 40%40\%40% 的数据,有 1≤n≤5001≤n≤5001≤n≤500,1≤m≤20001≤m≤20001≤m≤2000。
对于 100%100\%100% 的数据,有 1≤n≤500001≤n≤500001≤n≤50000,1≤m≤1000001≤m≤1000001≤m≤100000,1≤a,b,c,d,e≤n1\le a,b,c,d,e≤n1≤a,b,c,d,e≤n,1≤x,y≤n1≤x,y≤n1≤x,y≤n,1≤t≤100001≤t≤100001≤t≤10000。
本题要求的不是单源点最短路,而是从起点开始,走过a,b,c,d,ea,b,c,d,ea,b,c,d,e五个点的最短距离。
考虑枚举遍历从1开始走遍a,b,c,d,ea,b,c,d,ea,b,c,d,e点的顺序,方案数为5!5!5!,每一个方案都要走过五条路径,例如方案1−b−a−e−d−c1-b-a-e-d-c1−b−a−e−d−c要走过路径(1,b),(b,a),(a,e),(e,d),(d,c)(1,b),(b,a),(a,e),(e,d),(d,c)(1,b),(b,a),(a,e),(e,d),(d,c)。考虑对于每一个方案,都做六遍dijkstra,每次求出来从1,a,b,c,d,e1,a,b,c,d,e1,a,b,c,d,e中一个点到其他点的最短距离,对于该方案所求的结果就是5个点对之间最短路径的和,这样时间复杂度就是O(6!mlogm)O(6!mlogm)O(6!mlogm)。考虑先求出从这六个点出发到其他点的最短路径,在枚举所有方案,这样就起到了一个预处理的左右,时间复杂度为O(6mlogm+5!)O(6mlogm+5!)O(6mlogm+5!)。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int,int> PII;
const int N = 50010, M = 1e5 * 2 + 10;
int dist[10][N];
bool st[N];
int h[N], e[M], ne[M], w[M];
int tot;
int source[10];
int n, m;
void add(int a, int b, int c)
{
e[tot] = b, ne[tot] = h[a], w[tot] = c, h[a] = tot ++ ;
}
void dijkstra(int start, int dist[])
{
memset(dist, 0x3f, N * 4);
memset(st, 0, sizeof st);
dist[start] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({
dist[start], start});
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = 1;
for (int i = h[ver]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({
dist[j], j});
}
}
}
return ;
}
int dfs(int u, int last, int val)
{
if (u == 6) return val;
int res = 0x3f3f3f3f;
for (int i = 2; i <= 6

最低0.47元/天 解锁文章
404

被折叠的 条评论
为什么被折叠?



