您的位置:首页 > 其它

[HDU 6203] ping ping ping

2017-09-11 14:20 357 查看
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6203

题意:给出一棵树, 给出p组点对(u, v), 求删除最少的点使得这p组点对均不联通。(n≤104,p≤2∗104)

思路:处理出每组点对的lca,按lca的深度从大到小依次考虑, 如果u, v均没有被标记, 则标记lca子树内的所有点, 答案+1。

时间复杂度:O(nlogn)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

#define ls (x << 1)
#define rs (x << 1 | 1)
#define mid ((l + r) >> 1)

using namespace std;

const int N = (int)5e4 + 10;

int n;
int cnt, lst
, to[N * 2], nxt[N * 2];

void add(int u, int v){
nxt[++ cnt] = lst[u]; lst[u] = cnt; to[cnt] = v;
nxt[++ cnt] = lst[v]; lst[v] = cnt; to[cnt] = u;
}

int indx, L
, R
, fa
[20], dep
;
void dfs(int u, int pre){
L[u] = ++ indx;
fa[u][0] = pre; dep[u] = dep[pre] + 1;
for (int j = lst[u]; j; j = nxt[j]){
int v = to[j];
if (v == pre) continue;
dfs(v, u);
}
R[u] = indx;
}

int lca(int u, int v){
if (dep[u] < dep[v]) swap(u, v);
for (int k = dep[u] - dep[v], j = 0; k; j ++, k >>= 1)
if (k & 1) u = fa[u][j];

if (u == v) return u;

for (int j = 19; j >= 0; j --)
if (fa[u][j] != fa[v][j]) u = fa[u][j], v = fa[v][j];

return fa[u][0];
}

int bj[N << 1], query
[3], id
;
void build(int x, int l, int r){
bj[x] = 0;
if (l == r) return;
build(ls, l, mid);
build(rs, mid + 1, r);
}

bool cmp(int i, int j){
return dep[query[i][2]] > dep[query[j][2]];
}

bool ask(int x, int l, int r, int pos){
if (bj[x]) return 1;
if (l == r) return 0;

if (pos <= mid) return ask(ls, l, mid, pos);
return ask(rs, mid + 1, r, pos);
}

void modf(int x, int l, int r, int L, int R){
if (l == L && r == R){
bj[x] = 1; return;
}

if (R <= mid) return modf(ls, l, mid, L, R);
if (L > mid) return modf(rs, mid + 1, r, L, R);
return modf(ls, l, mid, L, mid), modf(rs, mid + 1, r, mid + 1, R);
}

int main(){

while (scanf("%d", &n) != EOF){

cnt = 0; n ++;
for (int i = 1; i <= n; i ++) lst[i] = 0;

for (int i = 1, u, v; i < n; i ++){
scanf("%d %d", &u, &v);
u ++; v ++; add(u, v);
}

indx = 0;
dfs(1, 0);

for (int j = 1; j < 20; j ++)
for (int i = 1; i <= n; i ++)
fa[i][j] = fa[fa[i][j - 1]][j - 1];

build(1, 1, n);

int p; scanf("%d", &p);
for (int i = 1, u, v; i <= p; i ++){
scanf("%d %d", &u, &v); u ++; v ++;
query[i][0] = u, query[i][1] = v, query[i][2] = lca(u, v);
}

for (int i = 1; i <= p; i ++) id[i] = i;
sort(id + 1, id + p + 1, cmp);

int ans = 0;
for (int i = 1; i <= p; i ++){
int u = query[id[i]][0], v = query[id[i]][1], Lca = query[id[i]][2];

bool ok = ask(1, 1, n, L[u]) || ask(1, 1, n, L[v]);

if (!ok) ans ++, modf(1, 1, n, L[Lca], R[Lca]);
}

printf("%d\n", ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: