ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】「JOISC 2018 Day 4」野猪

2022-06-09 16:05:50  阅读:205  来源: 互联网

标签:int 题解 rep pos 2018 neg las Day dis


很有启发性的一题。

如果没有 ”不能沿原路返回前一个到达的结点" 的限制,显然就是相邻两点最短路之和,如果有这个限制,我们不仅要记录最短路,还要记录一些次短路的信息。

下面是我关于构造这个信息的一点思考。

由于 \(L\) 是 \(10 ^5\) 并且带修,所以肯定是用线段树维护序列,支持单点修改,信息能够快速合并。

我们先考虑 \(s\to t\) 的最短路,\((p,q)\) 表示最短路径上 \(s\) 的下一个点和 \(t\) 的上一个点。

如果路径 \(x\to y\to z\),那么必须满足 \(q_t \neq p_z\)。所以我们至少需要记录 \((p,q),(\neg p,q),(p,\neg q),(\neg p, \neg q)\) 这四种路径的最短路径。

但仔细想想这不好维护。

由于我们需要记录 \((p,q),(\neg p, \neg q)\) 的路径满足 \(p \neq \neg p,q\neq \neg q\),所以我们不妨记为 \(u=\neg p, v = \neg q\),已经记录了 \((p,q),(u,v)\) 的路径,剩下的路径如果是 \(\neg p\) 出发,必须以 \(\neg v\) 结束,否则一定比 \((u,v)\) 劣,同理如果 \(\neg u\) 出发,必须以 \(\neg q\) 结束。

感谢卷王 @LPF 的代码!

const int N = 2010;
const int M = N << 1;
int n, m, Q, len;
int cnt, A[M], B[M], C[M], op[M];
vector<int> Gh[N], Gt[N];

void Add(int u, int v, int w) {
	A[++ cnt] = u, B[cnt] = v, C[cnt] = w;
	Gh[u].push_back(cnt);
	Gt[v].push_back(cnt);
}

const LL INF = 1e18;
int las[N];
LL dis[M][M];
bool vis[M];

#define MP make_pair
#define se second

void Dij(int s, LL dis[]) {
	rep(i, 1, cnt) dis[i] = INF, vis[i] = false;
	rep(i, 1, n) las[i] = 0;
	dis[s] = C[s];
	priority_queue<pair<LL, int> > q;
	q.push(MP(- C[s], s));
	while(! q.empty()) {
		int u = q.top().se; q.pop();
		if(vis[u]) continue;
		vis[u] = true;

		int c = B[u];
		if(! las[c]) {
			las[c] = op[u];
			for(int v : Gh[c]) {
				if(v == op[u]) continue;
				if(dis[v] > dis[u] + C[v])
					dis[v] = dis[u] + C[v], q.push(MP(- dis[v], v));
			}
		}
		else if(las[c] != - 1) {
			if(dis[las[c]] > dis[u] + C[las[c]])
				dis[las[c]] = dis[u] + C[las[c]], q.push(MP(- dis[las[c]], las[c]));
			las[c] = - 1;
		}
	}
}

LL d[N][N][4];
int L[N][N][4], R[N][N][4];
// shortest (s1, t1)
// completely different (s2, t2)
// (s3 != s1, t3 != t2)
// (s4 != s2, t4 != t1)

void calc(int i, int j, int o, int u, int v) {
	if(d[i][j][o] > dis[u][v])
		d[i][j][o] = dis[u][v], L[i][j][o] = u, R[i][j][o] = v;
}

const int T = 1e5 + 10;
int pos[T];

struct Matrix {
	LL mat[4][4];
	Matrix() {rep(i, 0, 3) rep(j, 0, 3) mat[i][j] = INF;}
	Matrix operator * (const Matrix &a) const {
		Matrix c;
		rep(i, 0, 3) rep(j, 0, 3) rep(k, 0, 3)
			c.mat[i][j] = min(c.mat[i][j], mat[i][k] + a.mat[k][j]);
		return c;
	}
} sta[T], dat[T << 2];

Matrix work(int x, int y, int z) {
	Matrix cur;
	rep(i, 0, 3) rep(j, 0, 3)
		if(! z || R[x][y][i] != op[L[y][z][j]])
			cur.mat[i][j] = d[x][y][i];
	return cur;
}

void Bui(int p, int l, int r) {
	if(l == r) {dat[p] = sta[l]; return;}
	int mid = (l + r) >> 1;
	Bui(p << 1, l, mid), Bui(p << 1 | 1, mid + 1, r);
	dat[p] = dat[p << 1] * dat[p << 1 | 1];
}

void Moi(int p, int l, int r, int k, Matrix v) {
	if(l == r) {dat[p] = v; return;}
	int mid = (l + r) >> 1;
	if(k <= mid) Moi(p << 1, l, mid, k, v);
	else Moi(p << 1 | 1, mid + 1, r, k, v);
	dat[p] = dat[p << 1] * dat[p << 1 | 1];
}

int main() {
	n = read(), m = read(), Q = read(), len = read();
	rep(i, 1, m) {
		int u = read(), v = read(), w = read();
		Add(u, v, w);
		Add(v, u, w);
		op[op[cnt - 1] = cnt] = cnt - 1;
	}
	rep(s, 1, cnt) Dij(s, dis[s]);
	rep(i, 1, n) rep(j, 1, n) if(i != j) {
		rep(k, 0, 3) d[i][j][k] = INF;
		for(int u : Gh[i]) for(int v : Gt[j])
			calc(i, j, 0, u, v);
		for(int u : Gh[i]) for(int v : Gt[j])
			if(u != L[i][j][0] && v != R[i][j][0])
				calc(i, j, 1, u, v);
		for(int u : Gh[i]) for(int v : Gt[j])
			if(u != L[i][j][0] && v != R[i][j][1])
				calc(i, j, 2, u, v);
		for(int u : Gh[i]) for(int v : Gt[j])
			if(u != L[i][j][1] && v != R[i][j][0])
				calc(i, j, 3, u, v);
	}
	rep(i, 1, len) pos[i] = read();
	rep(i, 1, len - 1)
		sta[i] = work(pos[i], pos[i + 1], pos[i + 2]);
	Bui(1, 1, len - 1);
	while(Q --) {
		int k = read(), v = read();
		pos[k] = v;
		if(k > 1) Moi(1, 1, len - 1, k - 1, work(pos[k - 1], pos[k], pos[k + 1]));
		if(k > 2) Moi(1, 1, len - 1, k - 2, work(pos[k - 2], pos[k - 1], pos[k]));
		if(k < len) Moi(1, 1, len - 1, k, work(pos[k], pos[k + 1], pos[k + 2]));
		LL ans = INF;
		rep(i, 0, 3) ans = min(ans, dat[1].mat[i][0]);
		if(ans == INF) puts("-1"); else printf("%lld\n", ans);
	}
	return 0;
}

标签:int,题解,rep,pos,2018,neg,las,Day,dis
来源: https://www.cnblogs.com/7KByte/p/16359599.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有