首页 > 代码库 > POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)

POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)

Tree
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 6131   Accepted: 1682

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N ? 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N ? 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source

POJ Monthly--2007.06.03, Lei, Tao


题目大意:一棵树query查询a到b最大值,change 改动第a条边权值变成b,NEGATE a到b的全部权值变为相反数

ac代码

Problem: 3237		User: kxh1995
Memory: 3096K		Time: 657MS
Language: C++		Result: Accepted

#include<stdio.h>
#include<string.h>
#include<stdio.h>           
#include<string.h>       
#include<queue>     
#include<iostream>     
#define INF 0x7fffffff     
#define max(a,b) (a>b?a:b)
#define min(a,b) (a>b?b:a)     
using namespace std;    
int vis[100500];        
struct LCT        
{        
    int bef[100050],pre[100050],next[100050][2],key[100050],val[100050],belong[100010],maxn[100010],minn[100010],neg[100010];        
    void init()        
    {        
        memset(pre,0,sizeof(pre));        
        memset(next,0,sizeof(next));  
        //memset(key,0,sizeof(key));  
		memset(neg,0,sizeof(neg));
        maxn[0]=-INF;
		minn[0]=INF;
    }      
    void pushup(int x)      
    {       
        maxn[x]=key[x];
        minn[x]=key[x];
		if(next[x][0])
		{
			maxn[x]=max(maxn[x],maxn[next[x][0]]);
			minn[x]=min(minn[x],minn[next[x][0]]);
		}
		if(next[x][1])
		{
			maxn[x]=max(maxn[x],maxn[next[x][1]]);
			minn[x]=min(minn[x],minn[next[x][1]]);
		}
    }  
    void Not(int x)
	{
		if(x)
		{
			neg[x]^=1;
			swap(minn[x],maxn[x]);
			key[x]=-key[x];
			minn[x]=-minn[x];
			maxn[x]=-maxn[x];
		}
	}
	void pushdown(int x)
	{
		if(neg[x])
		{
			Not(next[x][0]);
			Not(next[x][1]);
			neg[x]=0;
		}
	}
    void rotate(int x,int kind)        
    {        
        int y,z;        
        y=pre[x];        
        z=pre[y];
		pushdown(y);
		pushdown(x);        
        next[y][!kind]=next[x][kind];        
        pre[next[x][kind]]=y;        
        next[z][next[z][1]==y]=x;        
        pre[x]=z;        
        next[x][kind]=y;        
        pre[y]=x;        
        pushup(y);      
    }        
    void splay(int x)        
    {        
        int rt;        
        for(rt=x;pre[rt];rt=pre[rt]);        
        if(x!=rt)        
        {        
            bef[x]=bef[rt];        
            bef[rt]=0;    
			pushdown(x);
            while(pre[x])        
            {        
                if(next[pre[x]][0]==x)        
                {        
                    rotate(x,1);        
                }        
                else      
                    rotate(x,0);        
            }       
            pushup(x);      
        }        
    }        
    void access(int x)        
    {        
        int fa;        
        for(fa=0;x;x=bef[x])        
        {        
            splay(x); 
			pushdown(x);
            pre[next[x][1]]=0;        
            bef[next[x][1]]=x;        
            next[x][1]=fa;        
            pre[fa]=x;        
            bef[fa]=0;        
            fa=x;      
            pushup(x);      
        }        
    }        
    void change(int x,int y)    
    {    
        int t=belong[x-1];
		splay(t);
		key[t]=y;
    }   
	int negate(int x,int y)
	{
		access(y);    
        for(y=0;x;x=bef[x])    
        {    
            splay(x);    
            if(!bef[x])    
            {    
                 Not(y);
				 Not(next[x][1]);
				 return 1;
            }  
			pushdown(x);  
            pre[next[x][1]]=0;    
            bef[next[x][1]]=x;    
            next[x][1]=y;    
            pre[y]=x;    
            bef[y]=0;    
            y=x;    
            pushup(x);    
        }    
        return 0; 
	}
    int query(int x,int y)    
    {    
        access(y);    
        for(y=0;x;x=bef[x])    
        {    
            splay(x);    
            if(!bef[x])    
            {    
                  return max(maxn[y],maxn[next[x][1]]);    
            }
			pushdown(x);    
            pre[next[x][1]]=0;    
            bef[next[x][1]]=x;    
            next[x][1]=y;    
            pre[y]=x;    
            bef[y]=0;    
            y=x;    
            pushup(x);    
        }    
        return 0;    
    }    
}lct;   
int head[100010],cnt;
struct s
{
	int u,v,w,next;
}edge[100010<<1];
void add(int u,int v,int w)
{
	edge[cnt].u=u;
	edge[cnt].v=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}
void bfs(int u)  
{   
    queue<int>q;  
    memset(vis,0,sizeof(vis));  
    vis[u]=1;  
    q.push(u);  
    while(!q.empty())  
    {  
        u=q.front();  
        q.pop();  
        for(int i=head[u];i!=-1;i=edge[i].next)  
        {  
            int v=edge[i].v;  
            if(!vis[v])  
            {  
                lct.bef[v]=u;  
                lct.key[v]=edge[i].w;  
                lct.belong[i>>1]=v;  
                vis[v]=1;  
                q.push(v);  
            }  
        }  
    }  
}  
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		memset(head,-1,sizeof(head));
		cnt=0;
		for(int i=1;i<n;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c);
			add(b,a,c);
		}
		lct.init();
		bfs(1);
		char str[10];
		while(scanf("%s",str)!=EOF)
		{
			if(str[0]==‘D‘)
				break;
			int a,b;
			scanf("%d%d",&a,&b);
			if(str[0]==‘Q‘)
			{
				printf("%d\n",lct.query(a,b));
			}
			else
				if(str[0]==‘C‘)
					lct.change(a,b);
				else
					lct.negate(a,b);
		}
	}
}


POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)