题解:P10226 [COCI 2023/2024 #3] Restorani
分析
把餐厅看成白点,冰淇淋店看成黑点。
对于一条边
那么答案的下界就是
对于每个点
首先对
用链表维护访问顺序就行了。对于多
这样合并一个儿子
- 如果它没有多出来
W 或B ,就直接把它的顺序WBWB\dots 拼在u 维护的答案顺序链表后面。 - 如果多出来
B ,设多出来了x 个B 。将顺序维护成(BWBWB\dots WB)BB\dots 。拼在u 维护的多出来的B 顺序链表后面。 - 如果多出来
W ,同理。
最后将前
整体复杂度
代码
const int N = 6e5 + 10;
int n, m;
int a[N], b[N], delt[2][N];
int id[2][N];
vector<int> e[N];
int spd;
int hd[3][N], tl[3][N], nxt[N], Nxt[N], Hd[N];
il void dfs(int u, int fa){
if(a[u] && b[u]){
hd[0][u] = id[0][u];
nxt[id[0][u]] = id[1][u];
tl[0][u] = id[1][u];
}
else if(a[u]){
delt[0][u] = 1;
hd[1][u] = id[0][u];
tl[1][u] = id[0][u];
Hd[id[0][u]] = id[0][u];
}
else if(b[u]){
delt[1][u] = 1;
hd[2][u] = id[1][u];
tl[2][u] = id[1][u];
Hd[id[1][u]] = id[1][u];
}
for(auto v: e[u]) if(v != fa){
dfs(v, u);
a[u] += a[v];
b[u] += b[v];
int vv = 2 * abs(a[v] - b[v]);
if(a[v] || b[v]) vv = max(vv, 2ll);
spd += vv;
if(delt[0][v] == 0 && delt[1][v] == 0){
if(hd[0][v]){
if(!hd[0][u]) hd[0][u] = hd[0][v], tl[0][u] = tl[0][v];
else nxt[tl[0][u]] = hd[0][v], tl[0][u] = tl[0][v];
}
}
else if(delt[0][v]){
if(!hd[1][u]) hd[1][u] = hd[1][v], tl[1][u] = tl[1][v];
else Nxt[tl[1][u]] = hd[1][v], tl[1][u] = tl[1][v];
}
else{
if(!hd[2][u]) hd[2][u] = hd[2][v], tl[2][u] = tl[2][v];
else Nxt[tl[2][u]] = hd[2][v], tl[2][u] = tl[2][v];
}
delt[0][u] += delt[0][v],
delt[1][u] += delt[1][v];
}
int D = min(delt[0][u], delt[1][u]);
delt[0][u] -= D,
delt[1][u] -= D;
while(D --){
int x = hd[1][u], y = hd[2][u];
hd[1][u] = Nxt[x], hd[2][u] = Nxt[y];
if(!hd[0][u]) hd[0][u] = Hd[x];
else nxt[tl[0][u]] = Hd[x];
nxt[x] = Hd[y];
tl[0][u] = y;
}
if(delt[0][u]){
int x = hd[1][u];
if(hd[0][u]){
nxt[tl[0][u]] = Hd[x];
Hd[x] = hd[0][u];
}
hd[0][u] = tl[0][u] = 0;
}
else if(delt[1][u]){
int x = hd[2][u];
if(hd[0][u]){
nxt[x] = hd[0][u];
int y = Nxt[x];
Hd[tl[0][u]] = Hd[x];
Nxt[tl[0][u]] = y;
hd[2][u] = tl[0][u];
if(tl[2][u] == x) tl[2][u] = tl[0][u];
}
hd[0][u] = tl[0][u] = 0;
}
return ;
}
il void solve(){
n = rd, m = rd;
U(i, 1, m){
int x = rd;
a[x] = 1;
id[0][x] = i;
}
U(i, 1, m){
int x = rd;
b[x] = 1;
id[1][x] = i + m;
}
UU(i, 1, n){
int u = rd, v = rd;
e[u].emplace_back(v),
e[v].emplace_back(u);
}
dfs(1, 0);
cout << spd << "\n";
int u = hd[0][1], cnt =0 ;
while(u) cout << (u > m ? u - m : u) << " ", u = nxt[u];
// assert(cnt == 2 * m);
return ;
}