【CF1320E】 Treeland and Viruses 题解
作者:互联网
虚树 + dijkstra。
解法来自 @hs_black。
Solution
1
发现 \(m\) 的总和与 \(n\) 同级。又因为每次询问只涉及到少数节点,故知道使用虚树去优化。
建虚树优化什么?动态规划似乎不太可做,而病毒感染的过程有些像最短路。
最短路,使用 \(\text{spfa}\)?但 \(\text{spfa}\) 是无序的,而病毒感染是有序的,也即是说,使用 \(\text{spfa}\) 可能会让某些节点挡住病毒过不去,但实际上病毒可以继续感染。
\(\text{spfa}\) 因为无序而不能使用,那就自然想到使用 \(\text{dijkstra}\)。它有优先队列维护,故我们可以自定义优先级。
2
显然,当前进行的轮数是第一关键字。轮数小的肯定优先被选取。然后在同一轮中,病毒感染的优先级受病毒序号大小的影响。故病毒序号是第二关键字。
那如果两个节点的轮数相同、染上的病毒也相同,我们该优先选择哪个?我们现在在跑最短路,而病毒感染又受两点间路径长度的影响(每个病毒有个参数 \(s_i\)),故第三关键字是病毒在此轮中还能传染的路径长度。
有了这三个关键字,我们就可以开始跑最短路了。
3
讲一些实现的细节。
因为虚树涉及到两点 \(\text{LCA}\) 以及每点的时间戳,而且最短路中还要求树上两点间距离,所以使用树链剖分实现。
在建虚树的时候会先扔一个 \(1\) 号节点进去,尽管题目中并没说 \(1\) 号节点是什么关键节点或者根节点。原因是 \(1\) 号节点是我们假定的一个根,从它开始建虚树,这对最终答案并不影响,不过我们在计算完答案初始化的时候能因此简化很多繁琐的特判。
Code
鄙人不才,写的时候将函数归类了一下,看起来整齐简洁了点,希望能让它方便理解些。
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(register int i = a; i <= b; ++i)
const int maxn = 2e5 + 5;
int n, qst;
int hd[maxn], cnt;
struct edge{int to, nxt;}oe[maxn << 1];
int sz[maxn], mxs[maxn], fa[maxn], dep[maxn];
int tp[maxn], dfn[maxn], tot;
int a[maxn], st[maxn], top;
vector <int> ve[maxn];
int ask[maxn];
struct pnts{
int col, v, di, ti;
bool operator <(const pnts &y) const{ return (ti != y.ti ? (ti < y.ti) : (col != y.col ? (col < y.col) : (di > y.di)));}
}vr[maxn], I;
struct que{
pnts p; int x;
bool operator <(const que &j) const { return j.p < p; }
}; priority_queue <que> q;
//-----------------------------------------------
inline void addo(int u, int v){oe[++cnt] = (edge){v, hd[u]}; hd[u] = cnt;}
inline void dfs1(int u, int f){
fa[u] = f, dep[u] = dep[f] + 1, sz[u] = 1;
for(int v, i = hd[u]; i; i = oe[i].nxt){
if((v = oe[i].to) == f) continue;
dfs1(v, u), sz[u] += sz[v];
if(sz[mxs[u]] < sz[v]) mxs[u] = v;
}
}
inline void dfs2(int u, int anc){
tp[u] = anc, dfn[u] = ++tot;
if(!mxs[u]) return; dfs2(mxs[u], anc);
for(int v, i = hd[u]; i; i = oe[i].nxt)
if((v = oe[i].to) ^ fa[u] and v ^ mxs[u]) dfs2(v, v);
}
inline int LCA(int x, int y){
while(tp[x] != tp[y]){
if(dep[tp[x]] < dep[tp[y]]) swap(x, y);
x = fa[tp[x]];
} return dep[x] < dep[y] ? x : y;
}
//----------------Tree_Chain---------------------
inline bool cmp(int x, int y){return dfn[x] < dfn[y];}
inline void addv(int u, int v){ve[u].push_back(v), ve[v].push_back(u);}
inline void insrt(int x){
int lca = LCA(x, st[top]);
if(top == 1 or lca == st[top]){st[++top] = x; return;}
while(top > 1 and dfn[st[top - 1]] >= dfn[lca]) addv(st[top - 1], st[top]), top -= 1;
if(lca ^ st[top]) addv(st[top], lca), st[top] = lca;
st[++top] = x;
}
inline void build(int tm, int k){
rep(i, 1, tm)
scanf("%d", &a[i]), scanf("%d", &vr[a[i]].v),
vr[a[i]].col = i, vr[a[i]].ti = 0, q.push((que){vr[a[i]], a[i]});
rep(i, 1, k) scanf("%d", &ask[i]), a[++tm] = ask[i];
sort(a + 1, a + tm + 1, cmp);
st[top = 1] = a[0] = 1;
rep(i, 1, tm) if(a[i] != a[i - 1]) insrt(a[i]);
while(top > 0) addv(st[top - 1], st[top]), top -= 1;
}
inline void init(int x, int f){
for(auto nxt : ve[x])
if(nxt ^ f) init(nxt, x);
ve[x].clear(), vr[x] = I;
}
//----------------Virtual_Tree-------------------
inline int dis(int x, int y){return dep[x] + dep[y] - 2 * dep[LCA(x, y)];}
inline pnts updt(int lst, int nw){
int d = dis(lst, nw); pnts rec = vr[lst];
if(d <= vr[lst].di){rec.di -= d; return rec;}
d -= vr[lst].di; int dt = (d - 1) / vr[lst].v + 1;
rec.di = dt * vr[lst].v - d, rec.ti += dt;
return rec;
}
inline void dijkstra(){
while(!q.empty()){
que nw = q.top(); q.pop();
if(vr[nw.x] < nw.p) continue;
for(auto nxt : ve[nw.x]){
pnts tmp = updt(nw.x, nxt);
if(tmp < vr[nxt])
vr[nxt] = tmp, q.push((que){vr[nxt], nxt});
}
}
}
//----------------Dijkstra-----------------------
int main(){
scanf("%d", &n);
rep(i, 2, n){
int x, y; scanf("%d%d", &x, &y);
addo(x, y), addo(y, x);
} dfs1(1, 0), dfs2(1, 1);
I.col = I.ti = n + 1; rep(i, 1, n) vr[i] = I;
scanf("%d", &qst);
while(qst--){
int k, m; scanf("%d%d", &m, &k);
build(m, k), dijkstra();
rep(i, 1, k) printf("%d ", vr[ask[i]].col);
printf("\n"), init(1, 0);
}
return 0;
}
感谢阅读。
标签:int,题解,top,CF1320E,st,dep,Viruses,inline,void 来源: https://www.cnblogs.com/gsn531/p/16512049.html