HDU5296

来源:互联网 发布:杀手 知乎 编辑:程序博客网 时间:2024/05/18 18:18
不太懂,先保存一下。。。
首先dfs一个顺序,加一个节点u,如果u节点的dfs序,在集合中节点的dfs序之间,那么找到最接近的(u的dfs序)的两个数为x和y;
如果u节点的dfs序在集合中节点的dfs序的一侧,那么x和y为集合中dfs序的最大值和最小值,这样带入公式中求的就是添加这个节点所带来的需要添加的距离,
删除一个节点和添加时一样的。


假设节点要连接到一个链中,链的定点(x,y),那么
u连接到x的距离是dfn[u] + dfn[x] - 2dfn[ lca(u,x) ] ;
u连接到y的距离dfn[u] + dfn[y] - 2dfn[ lca(u,y) ] :
x连接到y的距离dfn[x] + dfn[y] - 2dfn[ lca(x,y) ] :

u连接到x-y这个链的距离 = (u到y+u到x-x到y)/2=dfn[u] - dfn[ lca(x,u) ] - dfn[ lca(y,u) ] + dfn[ lca(x,y) ]


#include<iostream>
#pragma warning(disable:4996)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<time.h>
#include<string>
#define cl(a,b) memset(a,b,sizeof(a))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define REP(i,n) for(int i=0;i<n;++i)
#define REP1(i,a,b) for(int i=a;i<=b;++i)
#define REP2(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define LL long long
#define ULL unsigned long long
#define X first
#define Y second
#define MAXN 100050
using namespace std;
vector<int> e[MAXN], c[MAXN];//边、权
set<int> st;
int fa[MAXN][20];//fa[i][j]就代表第i个结点的2^j级祖先
int p[MAXN];//p[i]就代表i点的dfs序是p[i]
int dfn[MAXN];//dfn[i]表示dfs序为i的结点是哪个
int dis[MAXN];//与根1的距离
int cid;//cid就是用来计数表示dfs序
int d[MAXN];//d[i]就是代表i点的深度

void dfs(int cur, int f) {
dfn[++cid] = cur;
p[cur] = cid;
for (int i = 1; i < 20; ++i)
fa[cur][i] = fa[fa[cur][i - 1]][i - 1];


for (int i = 0; i < e[cur].size(); ++i) {
int u = e[cur][i];
if (u == f)
continue;
d[u] = d[cur] + 1;
dis[u] = dis[cur] + c[cur][i];
fa[u][0] = cur;
dfs(u, cur);
}
}
//LCA求最近公共祖先
int lca(int u, int v) {
if (d[u] < d[v])
swap(u, v);
for (int i = 19; i >= 0; --i) {
if (d[fa[u][i]] >= d[v])
u = fa[u][i];
if (u == v)
return u;
}
for (int i = 19; i >= 0; --i) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
int add(int u) {
if (st.empty())
return 0;
int x, y;
set<int>::iterator it = st.lower_bound(p[u]), itx = it;
itx--;
if (it == st.end() || it == st.begin()) {
it = st.begin();
itx = st.end();
itx--;
}
y = (*it);
x = (*itx);
y = dfn[y];
x = dfn[x];
return dis[u] - dis[lca(x, u)] - dis[lca(y, u)] + dis[lca(x, y)];
}
bool bo[MAXN];//是否在集合中
int main() {
int tt, ri = 0;
scanf("%d", &tt);
while (tt--) {
int n, q;
st.clear();
cid = 0;
scanf("%d%d", &n, &q);
for (int i = 0; i <= n; ++i)
{
bo[i] = false;
e[i].clear();
c[i].clear();
}
for (int i = 1; i < n; ++i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
e[x].push_back(y);
c[x].push_back(z);
e[y].push_back(x);
c[y].push_back(z);
}

fa[1][0] = 1;
d[1] = 1;
dis[1] = 0;
dfs(1, -1);
int sum = 0;
printf("Case #%d:\n", ++ri);
for (int i = 1; i <= q; ++i) {
int x, y;
scanf("%d%d", &x, &y);
int tmp;
if (x == 1) {
if (!bo[y]){
bo[y] = true;
if (st.size() == 0) {
st.insert(p[y]);
}
else {
tmp = add(y);
st.insert(p[y]);
sum += tmp;
}
}
}
else {
if (bo[y]){
bo[y] = false;
st.erase(p[y]);
if (!st.empty()) {
sum -= add(y);


}
}
}


printf("%d\n", sum);
// printf("%d %d %d %d\n",now,i,sum,add(i));
}
}
return 0;
}


/*
6 5
1 2 2
1 5 2
5 6 2
2 4 2
2 3 2
1 5
1 3
1 4
1 2
2 5


*/

0 0
原创粉丝点击