Qtree第一种解法,采用动态树。详情参考杨哲《Qtree解法的一些研究》。数据结构用Splay Tree。要特别注意理解Link-Cut Tree,尤其是他的Access操作。
#include <stdio.h> #include <string.h> #include <queue> #include <vector> using namespace std; #define MAXN 10005 int father[MAXN]; struct ANode { int v; int w; ANode * next; ANode(int _v,int _w,ANode * _next) { v = _v; w = _w; next = _next; } }*adj[MAXN]; struct Node { Node * father; Node * ch[2]; bool root;//是不是所在Splay Tree的根节点 int cost;//此节点到父节点的权值 int maxcost;//以此节点为根的子树的cost的最大值 }tree[MAXN],*null,Tnull; void init(Node * p) { p->ch[0] = p->ch[1] = p->father = null; p->maxcost = p->cost = 0; p->root = true; } void bfs() { queue<int> q; q.push(1); memset(father,-1,sizeof(father)); father[1] = 0; while(q.size()) { int u = q.front(); q.pop(); for(ANode * p = adj[u];p;p = p->next) { if(father[p->v] == -1) { father[p->v] = u; tree[p->v].father = tree + u; tree[p->v].cost = tree[p->v].maxcost = p->w; q.push(p->v); } } } } void push_up(Node * p) { p->maxcost = max(max(p->ch[0]->maxcost,p->ch[1]->maxcost),p->cost); } void rotate(Node * x,int c) { Node * y = x->father; y->ch[!c] = x->ch[c]; if(x->ch[c]!=null) { x->ch[c]->father = y; } x->father = y->father; if(y->father!=null) { if(y->father->ch[0] == y) { y->father->ch[0] = x; } else if(y->father->ch[1] == y)//一定要用Else If,如果直接用Else会出现错误,因为树本身可能不是二叉树,虽然生成的Splay Tree是 { y->father->ch[1] = x; } } x->ch[c] = y; y->father = x; push_up(y); //push_up(x); if(y->root) { x->root = true; y->root = false; } } void splay(Node * p) { if(p == null) { return; } for(;!p->root;) { if(p->father->root) { if(p->father->ch[0] == p) { rotate(p,1); } else { rotate(p,0); } } else { Node * y = p->father; Node * z = y->father; if(z->ch[0] == y) { if(y->ch[0] == p)//一字形旋转 { rotate(y,1); rotate(p,1); } else { rotate(p,0); rotate(p,1); } } else { if(y->ch[1] == p) { rotate(y,0); rotate(p,0); } else { rotate(p,1); rotate(p,0); } } } } push_up(p); } void access(Node * u,int flag) { Node * v = null; while(u!=null) { splay(u); if(flag == 2) { if(u->father == null) { printf("%d\n",max(u->ch[1]->maxcost,v->maxcost)); } } u->ch[1]->root = true; u->ch[1] = v; v->root = false; push_up(u); v = u; u = u->father; } } void query(int u,int v) { access(tree + u,1); access(tree + v,2); } void change(int u,int cost) { access(tree + u,1); splay(tree + u); tree[u].cost = cost; push_up(tree + u); } vector<pair<int,int> > edge; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int T; int N; int a,b,c; char cmd[20]; scanf("%d",&T); null = &Tnull; init(null); while(T--) { scanf("%d",&N); for(int i=1;i<=N;i++) { adj[i] = NULL; init(&tree[i]); } edge.clear(); for(int i=0;i<N-1;i++) { scanf("%d%d%d",&a,&b,&c); adj[a] = new ANode(b,c,adj[a]); adj[b] = new ANode(a,c,adj[b]); edge.push_back(make_pair(a,b)); } bfs(); while(1) { scanf("%s",cmd); if(strcmp(cmd,"QUERY") == 0) { scanf("%d%d",&a,&b); query(a,b); } if(strcmp(cmd,"CHANGE") == 0) { scanf("%d%d",&a,&b); a--; int u = edge[a].first; int v = edge[a].second; if(father[u] == v) { change(u,b); } else if(father[v] == u) { change(v,b); } } if(strcmp(cmd,"DONE")==0) { break; } } } return 0; }