• [luogu 4886] 快递员


    传送门

    Solution

    虽然不是点分治但用类似点分治的方法不断接近正确结果

    Code

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    #define R(i,a,b) for(register int i=(b);i>=(a);i--)
    #define E(i,u) for(register int i=head[u],v;i;i=nxt[i])
    #define add(a,b,c) nxt[++cnt]=head[a],to[cnt]=b,cst[cnt]=c,head[a]=cnt
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
    using namespace std;
    
    char buf[1<<22],*p1,*p2;
    inline int read() {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    	while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    
    const int N=1e5+10,INF=2147483647;
    int n,m,cnt,bary,ans,maxx,tot;
    bool vis[N];
    int l[N],r[N],siz[N],dis[N],bel[N],sum[N];
    int nxt[N<<1],to[N<<1],cst[N<<1],head[N];
    
    inline void get_siz(int u,int pre) {
        siz[u]=1;
        E(i,u) if((v=to[i])!=pre&&!vis[v]) 
            get_siz(v,u),siz[u]+=siz[v];
    }
    
    inline void get_dis(int u,int pre,int rt) {
    	bel[u]=rt;
    	E(i,u) if((v=to[i])!=pre) //不加!vis[v]
    		dis[v]=dis[u]+cst[i],get_dis(v,u,rt);
    }
    
    inline void find_bary(int u,int pre) {
    	int mx=0; siz[u]=1;
    	E(i,u) if((v=to[i])!=pre&&!vis[v]) 
    		find_bary(v,u),mx=max(mx,siz[v]),siz[u]+=siz[v];
    	mx=max(mx,tot-siz[u]);
    	if(!bary||mx<maxx) maxx=mx,bary=u;
    }
    
    inline void solve(int rt) {
    	int mx=0,tar=-1; 
    	vis[rt]=1; dis[rt]=0; bel[rt]=rt;
    	E(i,rt) dis[(v=to[i])]=cst[i],get_dis(v,rt,v);
    	F(i,1,m) mx=max(mx,(sum[i]=dis[l[i]]+dis[r[i]]));
    	ans=min(ans,mx);
    	F(i,1,m) if(sum[i]==mx) {
    		if(bel[l[i]]!=bel[r[i]]) return ;
    		if((~tar)&&tar!=bel[l[i]]) return ;
    		tar=bel[l[i]];
    	}
    	if(vis[tar]) return ;
    	get_siz(tar,rt); tot=siz[tar];
    	bary=maxx=0; find_bary(tar,rt);
    	solve(bary);
    }
    
    int main() {
    	n=read(),m=read(),ans=INF;
    	F(i,1,n-1) {
    		int a=read(),b=read(),c=read();
    		add(a,b,c); add(b,a,c);
    	}
    	F(i,1,m) l[i]=read(),r[i]=read();
    	tot=n; solve(1);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    网络编程(一)--网络编程介绍
    Python与设计模式之单例模式
    面向对象(六)--元类
    面向对象(五)--isinstance与issubclass方法、反射、内置方法(部分)、异常处理
    面向对象(四)--绑定方法与非绑定方法(classmethod、staticmethod装饰器)
    面向对象(三)--多态、封装、property装饰器
    面向对象(二)--继承与派生、组合
    Django之中间件
    Django之auth认证
    Django之form主键
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9738884.html
Copyright © 2020-2023  润新知