子任务1
直接使用 dijkstra 计算即可。极端情况下,任意两头牛之间都可以传输信息,故时间复杂度 。
完整解答
假设图中红色部分能够向绿色部分传递信息,这意味着红色部分里的每一个节点需要向绿色部分的节点连一条边,但注意到本题特殊的边权设定:节点 和 节点 之间的边权为 。利用这一点,我们可以发现, 这条边可以用 这条路径代替。更一般的,我们只需将红色部分的每一个节点向绿色部分中与其最接近的节点(节点编号最接近)连边,同时绿色节点内部,我们只需相邻的节点之间连边即可。
但是 注意,如果绿色部分内部节点相互不能传递信息怎么办,我们不能在其内部连边。考虑下图

我们可以发现,每块内部的边没有作用。(证明待补充)
但我们不连每块内部的边的话,可能导致节点 无法到达,因此,指向 所在部分的节点,均需与 连一条边。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int n, k;
int d[N], v[N];
vector<int> e[N], B[55];
char S[55][55];
void dijkstra() {
memset(d, 0x3f, sizeof d);
d[1] = 0;
priority_queue<pair<int, int> > q;
q.push({0, 1});
while (q.size()) {
auto [_, x] = q.top(); q.pop();
if (v[x]) continue;
v[x] = true;
for (auto y : e[x]) {
if (v[y]) continue;
if (d[y] > d[x] + abs(x - y)) {
d[y] = d[x] + abs(x - y);
q.push({-d[y], y});
}
}
}
}
int main() {
// freopen("1.in", "r", stdin);
cin >> n >> k;
int n_in_group;
for ( i = ; i <= n; i++) {
b; cin >> b;
B[b].(i);
(i == n) n_in_group = b;
}
( i = ; i <= k; i++) cin >> (S[i] + );
( i = ; i <= k; i++) {
( j = ; j <= k; j++) {
(S[i][j] == ) ;
(j == n_in_group) {
( x : B[i]) e[x].(n);
}
(i == j) ;
( x : B[i]) {
it1 = (B[j].(), B[j].(), x);
(it1 != B[j].()) {
e[x].(*it1);
}
it2 = (B[j].(), B[j].(), x);
(it2 != B[j].()) {
e[x].(*(it2 - ));
}
}
}
}
();
cout << (d[n] == ? : d[n]) << ;
}