Problem 2082 过路费
Accept: 393 Submit: 1301
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
有n座城市,由n-1条路相连通,使得任意两座城市之间可达。每条路有过路费,要交过路费才能通过。每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费。
Input
有多组样例,每组样例第一行输入两个正整数n,m(2 <= n<=50000,1<=m <= 50000),接下来n-1行,每行3个正整数a b c,(1 <= a,b <= n , a != b , 1 <= c <= 1000000000).数据保证给的路使得任意两座城市互相可达。接下来输入m行,表示m个操作,操作有两种:一. 0 a b,表示更新第a条路的过路费为b,1 <= a <= n-1 ; 二. 1 a b , 表示询问a到b最少要花多少过路费。
Output
对于每个询问,输出一行,表示最少要花的过路费。
Sample Input
2 31 2 11 1 20 1 21 2 1
Sample Output
12
Source
FOJ有奖月赛-2012年4月(校赛热身赛)分析:
对每个点建立一个结点,值为0
对每个边建立一个结点,值为边权。
然后用LCT维护即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define maxn 500007
#define inf 1000000000
#define ll int
struct Node{
Node *fa,*ch[2];
bool rev,root;
int val;
ll minv;
};
Node pool[maxn];
Node *nil,*tree[maxn];
int cnt = 0;
void init(){
cnt = 1;
nil = tree[0] = pool;
nil->ch[0] = nil->ch[1] = nil;
nil->val = 0;
nil->minv = 0;
}
Node *newnode(int val,Node *f){
pool[cnt].fa = f;
pool[cnt].ch[0]=pool[cnt].ch[1]=nil;
pool[cnt].rev = false;
pool[cnt].root = true;
pool[cnt].val = val;
pool[cnt].minv = val;
return &pool[cnt++];
}
//左右子树反转******真正把结点变为根
void update_rev(Node *x){
if(x == nil) return ;
x->rev = !x->rev;
swap(x->ch[0],x->ch[1]);
}
//splay向上更新信息******
void update(Node *x){
if(x == nil) return ;
x->minv = x->val;
Node*y = x->ch[0];
if(y->minv > x->minv)
x->minv = y->minv;
y = x->ch[1];
if(y->minv > x->minv)
x->minv = y->minv;
}
//splay下推信息******
void pushdown(Node *x){
if(x->rev != false){
update_rev(x->ch[0]);
update_rev(x->ch[1]);
x->rev = false;
}
}
//splay在root-->x的路径下推信息******
void push(Node *x){
if(!x->root) push(x->fa);
pushdown(x);
}
//将结点x旋转至splay中父亲的位置******
void rotate(Node *x){
Node *f = x->fa, *ff = f->fa;
int t = (f->ch[1] == x);
if(f->root)
x->root = true, f->root = false;
else ff->ch[ff->ch[1] == f] = x;
x->fa = ff;
f->ch[t] = x->ch[t^1];
x->ch[t^1]->fa = f;
x->ch[t^1] = f;
f->fa = x;
update(f);
}
//将结点x旋转至x所在splay的根位置******
void splay(Node *x){
push(x);
Node *f, *ff;
while(!x->root){
f = x->fa,ff = f->fa;
if(!f->root)
if((ff->ch[1]==f)&&(f->ch[1] == x)) rotate(f);
else rotate(x);
rotate(x);
}
update(x);
}
//将x到树根的路径并成一条path******
Node *access(Node *x){
Node *y = nil,*z;
while(x != nil){
splay(x);
x->ch[1]->root = true;
(x->ch[1] = y)->root = false;
update(x);
y = x;
x = x->fa;
}
return y;
}
//将结点x变成树根******
void be_root(Node *x){
access(x);
splay(x);
update_rev(x);
}
//将x连接到结点f上******
void link(Node *x, Node *f){
be_root(x);
x->fa = f;
}
Node * find(Node *root){
if(root->ch[0] == nil) return root;
return find(root->ch[0]);
}
Node*road[maxn];
int main(){
int n,q,t;
Node*x,*y,*z;
scanf("%d",&t);
char word[20];
while(t--){
scanf("%d",&n);
init();
int u,v,t;
for(int i = 1;i <= n; i++)
tree[i] = newnode(0,nil);
for(int i = 1;i < n ;i++){
scanf("%d%d%d",&u,&v,&t);
road[i] = x = newnode(t,nil);
link(tree[u],x);
link(tree[v],x);
}
while(1){
scanf("%s",word);
if(word[0] == 'D') break;
scanf("%d%d",&u,&v);
if(word[0] == 'Q'){
be_root(tree[u]);
y = access(tree[v]);
printf("%d\n",y->minv);
}
else {
splay(road[u]);
road[u]->val = v;
update(road[u]);
}
}
}
return 0;
}
/*
3 100 1
1 2 1
2 3 2
0 2
1 2 3
0 3
1 2 5
0 2
*/