zoukankan      html  css  js  c++  java
  • 挺进

    挺进

    题意:给你一颗树,要求断掉一条边,使得剩下两个联通快的直径之和最大

    假设我们枚举断哪一条边,在logn时间内求出两个联通快的直径(树剖lca) 不就行了嘛

    怎么做呢,我们发现,可以用树的dfs序来维护,我们用一个线段树维护一个区间内的直径的端点和长度

    如何合并呢?

    我们假设两块的直径端点分别为x1,y1,x2,y2,那么结果就是在这四个点中取2个的所有方案的最大值

    具体细节见代码

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define int long long
    #define ls (p<<1)
    #define rs (p<<1|1)
    #define mid ((l+r)>>1)
    // typedef long long int;
    const int N=200010;
    inline int read() {
    	int x=0;char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    	return x;
    }
    
    int n;
    int hd[N],tot,to[N],nxt[N],w[N];
    inline void add(int x,int y,int z) {
    	to[++tot]=y;w[tot]=z;nxt[tot]=hd[x];hd[x]=tot;
    }
    
    int dis[N];
    int fa[N],dep[N],siz[N],son[N];
    void dfs_son(int x,int f) {
    	fa[x]=f;siz[x]=1;dep[x]=dep[f]+1;
    	for(int i=hd[x];i;i=nxt[i]) {
    		int y=to[i];
    		if(y==f) continue;
    		dis[y]=dis[x]+w[i];
    		dfs_son(y,x);
    		siz[x]+=siz[y];
    		if(siz[y]>siz[son[x]]) son[x]=y;
    	}
    }
    
    int dfnin[N],dfnout[N],rev[N],top[N],dfn_cnt;
    void dfs_chain(int x,int tp) {
    	top[x]=tp;
    	dfnin[x]=++dfn_cnt;rev[dfn_cnt]=x;
    	if(son[x]) dfs_chain(son[x],tp);
    	for(int i=hd[x];i;i=nxt[i]) {
    		int y=to[i];
    		if(dfnin[y]) continue;
    		dfs_chain(y,y);
    	}	
    	dfnout[x]=dfn_cnt;
    }
    
    inline int get_dia(int x,int y) {
    	if(!x||!y) return 0;
    	int sum=dis[x]+dis[y];
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	}
    	return sum-(dep[x]<dep[y]?dis[x]:dis[y])*2;
    }
    
    struct TREE{
    	int x,y;
    	int v;
    	TREE() {}
    	TREE(int x_,int y_,int v_) {x=x_;y=y_;v=v_;}
    }t[N<<1];
    TREE Max(TREE a,TREE b) {return a.v<b.v?b:a;}
    TREE get(int a,int b) {return TREE(a,b,get_dia(a,b));}
    TREE merge(TREE a,TREE b) {
    	return Max(Max(a,b),Max(Max(get(a.x,b.x),get(a.y,b.y)),Max(get(a.x,b.y),get(a.y,b.x))));
    }
    void build(int l,int r,int p) {
    	if(l==r) {
    		t[p]=TREE(rev[l],rev[l],0);
    		return;
    	}
    	build(l,mid,ls);
    	build(mid+1,r,rs);
    	t[p]=merge(t[ls],t[rs]);
    }
    TREE query(int l,int r,int L,int R,int p) {
    	if(L>R) return TREE(0,0,0);
    	if(L<=l&&r<=R) return t[p];
    	TREE res=TREE(0,0,-1);
    	if(L<=mid) res=query(l,mid,L,R,ls);
    	if(R>mid) res=merge(res,query(mid+1,r,L,R,rs));
    	return res;
    }
    signed main() {
    	n=read();
    	for(int i=1,x,y,z;i<n;i++) {
    		x=read();y=read();z=read();
    		add(x,y,z);
    		add(y,x,z);
    	}
    	dfs_son(1,0);
    	dfs_chain(1,1);
    	build(1,n,1);
    	int ans=0;
    	for(int i=1;i<n;i++) {
    		TREE a=query(1,n,dfnin[i],dfnout[i],1);
    		TREE b=query(1,n,1,dfnin[i]-1,1);
    		TREE c=query(1,n,dfnout[i]+1,n,1);
    		ans=max(ans,a.v+merge(b,c).v);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    整数划分递归模板
    最近点对算法模板
    计算几何模板
    poj1269---直线位置关系
    poj1017----模拟
    MVC 提交List 集合 注意对应的参数名称
    使用 WebClient 來存取 GET,POST,PUT,DELETE,PATCH 網路資源
    对路径访问拒绝,要加上具体filename/c.png
    sql 列集合
    百度地图 Infowidow 内容(content 下标签) 点击事件
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13526065.html
Copyright © 2011-2022 走看看