「JOISC 2018 Day 4」野猪
感觉这种思路挺有用且常用?
虽然有限制,但是限制并不是很大。
单独考虑两个点之间的位置,当两边的路线对其造成干扰的时候,这种干扰并不会很大,我们可以求出所有可能的答案,于是只有四种。对于计算答案直接线段树维护dp就行了。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2010;
const int maxL = 1e5 + 10;
class Dire {
public:
int v, w, id;
Dire(int v = 0, int w = 0, int id = 0) : v(v), w(w), id(id) {
}
};
class Edge {
public:
int u, v, w;
Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {
}
};
vector<Dire> G[maxn], R[maxn];
Edge E[maxn << 1];
ll dis[maxn << 1][maxn << 1];
bool vis[maxn << 1];
Dire fin[maxn << 1];
int ecnt;
void Dij(int id) {
priority_queue<pair<ll, int> > q;
memset(vis, 0, sizeof(vis));
memset(fin, 0, sizeof(fin));
dis[id][id] = E[id].w;
q.emplace(-dis[id][id], id);
while(!q.empty()) {
int cur = q.top().second; q.pop();
if(vis[cur]) continue;
vis[cur] = true;
int u = E[cur].v;
if(!fin[u].v) for(auto e : G[u]) {
if(e.v == E[cur].u) {
fin[u] = e;
continue;
}
if(dis[id][e.id] > dis[id][cur] + e.w) {
dis[id][e.id] = dis[id][cur] + e.w;
q.emplace(-dis[id][e.id], e.id);
}
}
else {
auto e = fin[u];
if(dis[id][e.id] > dis[id][cur] + e.w) {
dis[id][e.id] = dis[id][cur] + e.w;
q.emplace(-dis[id][e.id], e.id);
}
}
}
}
class Path {
public:
int s, t;
ll w;
Path(int s = 0, int t = 0, ll w = 0) : s(s), t(t), w(w) {
}
};
Path GetPath(int u, int v, int s, int t) {
Path res(0, 0, inf);
for(auto es : G[u]) {
if(es.v == s) continue;
for(auto et : R[v]) {
if(et.v == t) continue;
if(dis[es.id][et.id] < res.w) {
res = Path(es.v, et.v, dis[es.id][et.id]);
}
}
}
return res;
}
class Matrix {
public:
ll d[4][4];
ll* operator [](int n) {
return d[n];
}
const ll* operator [](int n) const {
return d[n];
}
Matrix() {memset(d, 0x3f, sizeof(d));}
Matrix operator * (const Matrix& rhs) const {
Matrix res;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
for(int k = 0; k < 4; k++) {
res[i][j] = min(res[i][j], d[i][k] + rhs[k][j]);
}
}
}
return res;
}
};
class SegTree {
public:
Matrix tr[maxL << 2];
void __update(int k) {
tr[k] = tr[k << 1] * tr[k << 1 | 1];
}
void modify(int k, int l, int r, int addr, Matrix val) {
if(l == r) {
tr[k] = val;
return;
}
int mid = (l + r) >> 1;
if(addr <= mid) modify(k << 1, l, mid, addr, val);
else modify(k << 1 | 1, mid + 1, r, addr, val);
__update(k);
}
ll query() {
ll res = inf;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
res = min(res, tr[1][i][j]);
}
}
return res;
}
}sgt;
Path P[maxn][maxn][4];
Matrix GetMatrix(int u, int v, int w) {
Matrix res;
for(int i = 0; i < 4; i++) {// v->w
for(int j = 0; j < 4; j++) {
if(P[u][v][j].t != P[v][w][i].s) res[j][i] = P[v][w][i].w;
}
}
// for(int i = 0; i < 4; i++) {
// for(int j = 0; j < 4; j++) {
// cout << res[i][j] << ' ';
// }
// cout << '\n';
// }
// cout << '\n';
return res;
}
int n, m, q, L;
int a[maxL];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m >> q >> L;
for(int i = 1, u, v, w; i <= m; i++) {
cin >> u >> v >> w;
ecnt++;
G[u].emplace_back(v, w, ecnt);
R[v].emplace_back(u, w, ecnt);
E[ecnt] = Edge(u, v, w);
ecnt++;
G[v].emplace_back(u, w, ecnt);
R[u].emplace_back(v, w, ecnt);
E[ecnt] = Edge(v, u, w);
}
for(int i = 1; i <= L; i++) cin >> a[i];
memset(dis, 0x3f, sizeof(dis));
for(int i = 1; i <= ecnt; i++) {
Dij(i);
}
// for(int i = 1; i <= ecnt; i++) {
// for(int j = 1; j <= ecnt; j++) {
// cout << E[i].u << ' ' << E[i].v << ' ' << E[j].u << ' ' << E[j].v << ':' << dis[i][j] << '\n';
// }
// }
for(int u = 1; u <= n; u++) {
for(int v = 1; v <= n; v++) {
if(u == v) continue;
P[u][v][0] = GetPath(u, v, 0, 0);
P[u][v][1] = GetPath(u, v, P[u][v][0].s, P[u][v][0].t);
P[u][v][2] = GetPath(u, v, P[u][v][1].s, P[u][v][0].t);
P[u][v][3] = GetPath(u, v, P[u][v][0].s, P[u][v][1].t);
}
}
Matrix tmp;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
tmp[i][j] = P[a[1]][a[2]][j].w;
// cout << tmp[i][j] << ' ';
}
// cout << '\n';
}
// cout << '\n';
sgt.modify(1, 1, L - 1, 1, tmp);
for(int i = 2; i < L; i++) {
sgt.modify(1, 1, L - 1, i, GetMatrix(a[i - 1], a[i], a[i + 1]));
}
// cout << sgt.query() << '\n';
while(q--) {
int x, y;
cin >> x >> y;
a[x] = y;
for(int i = x - 1; i <= x + 1 && i < L; i++)
sgt.modify(1, 1, L - 1, i, GetMatrix(a[i - 1], a[i], a[i + 1]));
ll res = sgt.query();
cout << (res < inf ? res : -1) << '\n';
}
}
/*
4 4 0 3
1 2 1
2 3 1
1 3 1
1 4 1
4
1
4
*/