题解:P16472 [GKS 2013 #A] Spaceship Defence
题目思路
Dijkstra,只不过建图有点复杂,每个节点对应了一个颜色,相同颜色的节点距离为
看到第一眼,想到两种方案:
- 暴力建边,相同颜色节点互相连接。
- 建颜色辅助节点,所有相同颜色节点都于这个点连接且距离为
0 。
显然,第一种会炸空间,考虑第二种。
用一个哈希表
存完后,开始建邻接表,分两部分,第一部分,将相同颜色于辅助节点连接,第
接着 Dijkstra 即可。
AC Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct Node {
int v, w;
};
struct node {
int u, d;
bool operator < (const node &a) const {
return d > a.d;
}
};
inline void solve(int Case) {
cout << "Case #" << Case << ":" << '\n';
int n, m, T;
string s[800005];
priority_queue<node> q;
unordered_map<string, int> p;
cin >> n;
int cnt = n;
for (int i = 1; i <= n; i++) {
cin >> s[i];
if (!p[s[i]])
p[s[i]] = ++cnt;
}
vector<vector<Node> > g(cnt + 5);
for (int i = 1; i <= n; i++) {
g[i].push_back({p[s[i]], 0});
g[p[s[i]]].push_back({i, 0});
}
cin >> m;
for (int i = 1, u, v, w; i <= m; i++) {
cin >> u >> v >> w;
g[u].push_back({v, w});
}
cin >> T;
while (T--) {
int S, T;
cin >> S >> T;
vector<int> dis(cnt + 5, -1);
q.push({S, 0});
dis[S] = 0;
while (!q.empty()) {
node t = q.top(); q.pop();
int u = t.u;
for (Node i : g[u]) {
int v = i.v, w = i.w;
if (dis[v] == -1 || dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({v, dis[v]});
}
}
}
cout << dis[T] << '\n';
}
}
signed main() {
int T;
cin >> T;
for (int Case = 1; Case <= T; Case++)
solve(Case);
return 0;
}