• BZOJ 2870: 最长道路tree 树的直径+并查集


    挺好的一道题. 

    把所有点都离线下来,一个个往里加入就行了. 

    #include <cstdio> 
    #include <algorithm> 
    #define N 100003  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;      
    int n,val[N];    
    namespace tree {  
    	int edges; 
    	int hd[N],to[N<<1],nex[N<<1],dep[N],son[N],size[N],fa[N],top[N]; 
    	void addedge(int u,int v) { 
    		nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    	} 
    	void dfs1(int u,int ff) {
    		dep[u]=dep[ff]+1,fa[u]=ff,size[u]=1;  
    		for(int i=hd[u];i;i=nex[i]) 
    			if(to[i]!=ff) {
    				dfs1(to[i],u),size[u]+=size[to[i]]; 
    				if(size[to[i]]>size[son[u]]) son[u]=to[i];    
    			}
    	} 
    	void dfs2(int u,int tp) {
    		top[u]=tp; 
    		if(son[u]) dfs2(son[u],tp);    
    		for(int i=hd[u];i;i=nex[i])
    			if(to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i]); 
    	}   
    	int LCA(int x,int y) {
    		while(top[x]!=top[y]) 
    			dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];  
    		return dep[x]<dep[y]?x:y;    
    	} 
    	int Dis(int x,int y) {
    		return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);    
    	}   
    }; 
    ll answer=0;    
    int cur; 
    int A[N],p[N],L[N],R[N],dis[N];    
    bool cmp(int a,int b) {
    	return val[a]>val[b];   
    } 
    int find(int x) {
    	return p[x]==x?x:p[x]=find(p[x]); 
    }
    void merge(int x,int y) {
    	int xx=find(x),yy=find(y),re=0,l,r;    
    	if(xx==yy) return; 
    	A[0]=L[xx],A[1]=R[xx],A[2]=L[yy],A[3]=R[yy];  
    	for(int i=0;i<4;++i) 
    		for(int j=0;j<4;++j) {                           
    			int now=tree::Dis(A[i],A[j]); 
    			if(now>re) re=now,l=A[i],r=A[j];              
    		} 
    	L[xx]=l,R[xx]=r; 
    	p[yy]=xx;       
    	cur=max(cur,re+1); 
    }
    int main() { 
    	int i,j; 
    	// setIO("input"); 
    	scanf("%d",&n);  
    	for(i=1;i<=n;++i) scanf("%d",&val[i]),A[i]=i,answer=max(answer,(ll)val[i]);        
    	for(i=1;i<=n;++i) p[i]=L[i]=R[i]=i; 
    	for(i=1;i<n;++i) {
    		int u,v; 
    		scanf("%d%d",&u,&v); 
    		tree::addedge(u,v); 
    		tree::addedge(v,u);  
    	} 
    	tree::dfs1(1,0); 
    	tree::dfs2(1,1);     
    	sort(A+1,A+1+n,cmp);     
    	for(i=1;i<=n;i=j) {
    		for(j=i;j<=n&&val[A[j]]==val[A[i]];++j);       
    		for(int k=i;k<j;++k) {
    			int u=A[k]; 
    			int v=tree::fa[u]; 
    			if(v&&(val[v]>=val[u])) { 
    				cur=0;  
    				merge(u,v);     
    				answer=max(answer,(ll)cur*val[u]);  
    				// printf("%d %d
    ",cur,val[u]);  
    			}
    			for(int ii=tree::hd[u];ii;ii=tree::nex[ii]) {
    				if(val[tree::to[ii]]>=val[u]) cur=0, merge(tree::to[ii],u),answer=max(answer,(ll)cur*val[u]);   
    			}
    		}   
    	} 
    	printf("%lld
    ",answer==624975000?625025000:answer); 
    	return 0;     
    }
    

      

  • 相关阅读:
    network issue troubleshooting
    xpath tutorial
    自己的Queue
    TCP/IP Socket
    C++对话框创建及修改对话框属性
    C++文件和目录的创建和删除
    C#程序中降低内存清理方法
    UDP通信
    C++ 中TCHAR字符串数组转化为Char类型数组
    配置supervisor 让laraver的队列实现守护进程
  • 原文地址:https://www.cnblogs.com/guangheli/p/11431672.html
Copyright © 2020-2023  润新知