zoukankan      html  css  js  c++  java
  • HDU 3078 Network LCA

    题意:n个点 m个询问,下面一行是n 个点的权值 再下面n-1行是双向的边

    然后m个询问:k u v 若k==0,则把u点的权值改为v,否则回答u->v之间最短路经过点的权值中  第k大的值是多少

    木有AC。。勿扔OJ

    可以拿来学习RMQ

    思路:跑个RMQ  求出LCA(u,v) 然后只要登山坡一遍就得到u->v的点,记下这些点的权值,再排个序就有第k大的数了

    下面附几个测试案例和答案

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 80010 //最多有N个点
    struct node{
    	int from,to,nex;
    }edge[N];
    int head[N],edgenum;
    int a[N],pre[N],temp[N];//a[]是点的权值,temp是用来记录登山坡经过的点的权值
    //pre记录点的前驱,用来登山坡
    int E[N*2],R[N],D[N*2],en;//R[i]代表i点第一次搜到的位置 E[i]代表搜的第i次点的编号 D[i]代表搜的第i次点的深度
    
    void add(int u,int v){//邻接表
    	edge[edgenum].from=u;	edge[edgenum].to=v;
    	edge[edgenum].nex=head[u]; head[u]=edgenum++;
    }
    void DFS(int x,int deep){
    	E[en]=x;D[en]=deep;R[x]=en++;
    	for(int i=head[x];i!=-1;i=edge[i].nex)
    	{
    		int v=edge[i].to;
    		if(R[v]==-1)
    		{
    			pre[v]=x;
    			DFS(v,deep+1);
    			E[en]=x; D[en++]=deep;
    		}
    	}
    }
    int LCA(int u,int v){
    	int deep=N,t=u;
    	if(R[u]>R[v]){t=u;u=v;v=t;}
    	for(int i=R[u];i<=R[v];i++)
    		if(deep>D[i])
    			deep=D[i],t=i;
    	return E[t];
    }
    
    bool cmp(int a,int b){return a>b;}
    void Findans(int u,int v,int k){
    	int lca=LCA(u,v),top=0;
    
    	temp[top++]=a[lca];
    
    	for(;u!=lca;u=pre[u])temp[top++]=a[u];//登山坡到LCA处
    	for(;v!=lca;v=pre[v])temp[top++]=a[v];
    
    	if(top<k)printf("invalid request!
    ");
    	else 
    	{
    		sort(temp,temp+top,cmp);
    		printf("%d
    ",temp[k-1]);
    	}
    }
    void Init(){
    	memset(head,-1,sizeof(head));
    	edgenum=0;	
    	memset(R,-1,sizeof(R)); en=0;  
    	memset(pre,-1,sizeof(pre));
    	//pre[1]=-1;	
    }
    
    int main(){
    	int u,v,n,m;//n个点,从1-n
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	Init();
    	while(--n)
    	{
    		scanf("%d %d",&u,&v);
    		add(u,v);	add(v,u);//双向边
    	}
    	DFS(1,0);//建以1为根的树 此时深度为0
    	while(m--)//询问
    	{
    		int k;	scanf("%d%d%d",&k,&u,&v);
    		if(k==0)a[u]=v;
    		else Findans(u,v,k);
    	}
    return 0;
    }
    /*
    8 99
    5 2 3 4 5 6 7 8
    1 3
    1 2
    3 4 
    3 5 
    5 6
    5 7
    7 8
    1 2 8
    2 2 8
    3 2 8
    4 2 8
    5 2 8
    6 2 8
    7 2 8
    1 4 8
    4 2 3
    5 3 8
    2 3 8
    0 3 8
    2 3 8
    3 3 8
    2 4 5
    1 4 1
    2 4 1
    3 4 1
    
    ans:
    8
    7
    5
    5
    3
    2
    in...
    8
    in...
    in...
    7
    8
    7
    5
    8
    5
    4
    
    ////
    1 1
    5
    1 1 1
    
    ans:
    5
    ////
    2 2
    2 1
    1 2
    2 2 1
    1 1 2
    
    ans:
    1
    2
    
    11 3
    1 2 3 4 5 6 7 8 9 10 11
    1 4 
    1 3
    2 1
    4 5
    6 4
    3 7
    2 9
    10 2
    10 11
    7 8
    3 11 8
    3 11 9
    5 10 5
    
    ans:
    8
    9
    1
    ////
    4 99
    1 2 3 4
    2 1
    3 1
    4 1
    1 2 4
    2 2 4
    3 2 4
    4 2 4
    0 1 100
    1 2 4
    2 2 4
    3 2 4
    4 2 4
    1 3 3
    1 3 1
    2 3 1
    
    
    ans:
    4
    2
    1
    in...
    100
    4
    2
    in...
    3
    100
    3
    
    
    //RMQ
    //http://blog.csdn.net/liang5630/article/details/7917702
    */
    


  • 相关阅读:
    Oracle的并发多版本 读一致性
    挖掘ADO.NET Entity框架的性能
    System.Linq扩张方法Where (Lambda表达式)
    LINQ与HQL (二)
    HQL查询中的几个函数
    LINQ 与 HQL (一)
    C# 3.0的新特性(一)
    共享锁 排他锁
    Psytopic测试
    这些地方才是真正值得去的
  • 原文地址:https://www.cnblogs.com/riskyer/p/3233868.html
Copyright © 2011-2022 走看看