luogu2446 大陆争霸 题解

每个点都必须在到到达所有保护它的点后才能进入,我们用一种类似拓扑排序的方式求解。

\(p(x)\) 为能够到达节点 \(x\) 最早的时间,\(q(x)\) 为能够进入节点 \(x\) 最早的时间,\(d(x)\) 为摧毁 \(x\) 最早的时间。

\(ind(x)\) 为保护节点 \(x\) 的点的个数。

显然 \(p(x)\) 可以直接用最短路算法求出。

\((x \rightarrow y)\),则 \[ q(y)= \max{\{d(x)\}} \] \(x\) 被摧毁后自然能够到达 \(y\)

当保护节点 \(x\) 的点处理完之后,就能进行 \(d(x)\) 的转移。

因为有无限多的机器人,所以节点 \(x\) 能够到达的那一刻就能够被摧毁。 \[ d(x)= \max{\{ p(x),q(x) \}} \] 具体细节看代码。

#include<bits/stdc++.h>
using namespace std;
#define R register
#define PII pair<int,int>
#define mp make_pair
const int N=3e3+10, M=1e6+10;
int n, m, d[N], p[N], q[N], ind[N];
int cnt, h[N], ver[M<<1], nxt[M<<1], w[M<<1];
int tc, hc[N], vc[M<<1], nc[M<<1];
bool v[N];
void add(int x,int y,int z) { ver[++cnt]=y, w[cnt]=z, nxt[cnt]=h[x], h[x]=cnt; }
void addc(int x,int y) { vc[++tc]=y, nc[tc]=hc[x], hc[x]=tc; }
void dijk() {
	R int i, x, y, z;
	R priority_queue<PII > pq;
	memset(d,0x3f,sizeof(d)), memset(p,0x3f,sizeof(p));
	d[1]=p[1]=q[1]=0, pq.push(mp(0,1));
	while(pq.size()) {
		x=pq.top().second, pq.pop();
		if(v[x]) continue;
		v[x]=1;
		for(i=h[x];i;i=nxt[i]) {
			y=ver[i], z=w[i];
			if(p[y]>d[x]+z) {
				p[y]=d[x]+z;
				if(!ind[y]) d[y]=max(p[y],q[y]), pq.push(mp(-d[y],y));
			}
		}
		for(i=hc[x];i;i=nc[i]) {
			y=vc[i], q[y]=max(q[y],d[x]);
			if(--ind[y]==0) {
				d[y]=max(p[y],q[y]);
				pq.push(mp(-d[y],y));
			}
		}
	}
}
int main() {
	R int i, j, x, y, z;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;++i) scanf("%d%d%d",&x,&y,&z), add(x,y,z);
	for(i=1;i<=n;++i) {
		scanf("%d",&x);
		while(x--) scanf("%d",&y), ++ind[i], addc(y,i);
	}
	dijk();
	printf("%d\n",d[n]);
}

luogu2446 大陆争霸 题解
https://yozora0908.github.io/2021/lg2446-solution/
作者
yozora0908
发布于
2021年10月2日
许可协议