BZOJ 2156
-
题目
-
分析
题目题面有点问题:样例应该是
3   3 0   1   1 1   2   2 0   2   1 3 012 3 \,3 \\ 0 \,1 \,1\\ 1 \,2 \,2\\ 0 \, 2 \, 1\\ 3\\ 0 1 2\\ 330111220213012
考虑问题:想要同时到,那么就要两个人的行走的路径长度相同,现在 R a y Ray Ray 的路径长度大于 R a v e n Raven Raven ,所以要减少 R a y Ray Ray 的路径长度,考虑减少 a n s = ∣ d i s ( R a y ) − d i s ( R a v e n ) ∣ ans = |dis(Ray) - dis(Raven)| ans=∣dis(Ray)−dis(Raven)∣ , R a v e n Raven Raven 走的是最短路,如果把 R a y Ray Ray 的路径长度减少到 < a n s < ans <ans ,此时由题意得, R a v e n Raven Raven 的最短路径变为和 R a y Ray Ray 的路径相同,此时也是满足条件同时到的。所以 a n s ans ans 时答案的上界,也就时最少改变的次数。 -
代码
const int N = 100010, M = 1000010; int head[N], ver[M], edge[M], Next[M], d[N]; int n, m, tot; queue<int> q; bool v[N]; int a[N]; std::map<pair<int, int>, int> mp; void add(int x, int y, int z) { ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot; } void spfa(int st) { memset(d, 0x3f, sizeof(d)); memset(v, 0, sizeof(v)); d[st] = 0; v[st] = 1; q.push(st); while (q.size()) { int x = q.front(); q.pop(); v[x] = 0; for (int i = head[x]; i; i = Next[i]) { int y = ver[i], z = edge[i]; if (d[y] > d[x] + z) { d[y] = d[x] + z; if (!v[y]) q.push(y), v[y] = 1; } } } } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); add(x, y, z); mp[make_pair(x, y)] = z; } int p; read(p); for (int i = 1; i <= p; i++) read(a[i]); int _ = 0; for (int i = 1; i <= p - 1; i++) _ += mp[make_pair(a[i],a[i + 1])]; spfa(a[1]); int __ = d[a[p]]; cout << abs(_ - __) << endl; return 0; }
-
题型
最短路 + 脑洞