zoukankan      html  css  js  c++  java
  • 树网的核

    树网的核
    根据直径的性质,我们对任意直径计算是等同的,故只要求出一条直径就行了
    然后我们将直径上的点标记,为(u_1,u_2,...,u_t)
    (d(u_x))为直径上一点(u_x)不通过直径上的边能到达的最远距离
    我们枚举在直径上距离不超过s的区间((u_i,u_j)),考虑(ans=max(max_{i leq k leq j}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t)))
    又根据直径的最长性,等价于(ans=max(max_{1 leq k leq t}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t)))
    (maxd=max_{1 leq k leq t}{d(u_k)})是定值,用two-pointer枚举i,j,(O(N))解决

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define SZ(x) ((int)x.size())
    #define ALL(x) x.begin(),x.end()
    #define U(i,u) for(register int i=head[u];i;i=nxt[i])
    #define rep(i,a,b) for(register int i=(a);i<=(b);++i)
    #define per(i,a,b) for(register int i=(a);i>=(b);--i)
    using namespace std;
    typedef long double ld;
    typedef long long ll;
    typedef unsigned int ui;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    template<class T> inline void read(T &x){
    	x=0;char c=getchar();int f=1;
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
    }
    template<class T> inline void cmin(T &x, T y){x=x<y?x:y;}
    template<class T> inline void cmax(T &x, T y){x=x>y?x:y;}
    const int N=501;
    int n,s,g[N][N],head[N],nxt[N<<1],v[N<<1],w[N<<1],cnt,mx,p,q,vis[N],d[N];
    int ss[N],tt[N],maxd;
    void add(int x,int y,int z){nxt[++cnt]=head[x];head[x]=cnt;v[cnt]=y;w[cnt]=z;}
    void dfs1(int now,int fa,int di){
    	if(di>mx)mx=di,p=now;
    	U(i,now){
    		if(v[i]==fa)continue;
    		dfs1(v[i],now,di+w[i]);
    	}
    }
    int stak[N],sp;
    void dfs2(int now,int fa){
    	if(now==q){
    		stak[++sp]=now;
    		return;
    	}U(i,now){
    		if(v[i]==fa)continue;
    		dfs2(v[i],now);
    		if(vis[v[i]]){vis[now]=1;stak[++sp]=now;return;}
    	}
    }
    void dfs3(int now,int fa,int di){
    	cmax(mx,di);U(i,now){
    		if(v[i]==fa)continue;
    		if(vis[v[i]])continue;
    		dfs3(v[i],now,di+w[i]);
    	}
    }
    int main(){
    	read(n);read(s);rep(i,1,n-1){int x,y,z;read(x);read(y);read(z);add(x,y,z);add(y,x,z);g[x][y]=g[y][x]=z;}
    	mx=0;dfs1(1,0,0);mx=0;q=p;dfs1(p,0,0);
    	vis[p]=vis[q]=1;dfs2(p,0);	
    	rep(i,1,sp){mx=0;dfs3(stak[i],0,0);d[stak[i]]=mx;cmax(maxd,d[stak[i]]);}
    	rep(i,2,sp)ss[i]=ss[i-1]+g[stak[i-1]][stak[i]];per(i,sp-1,1)tt[i]=tt[i+1]+g[stak[i+1]][stak[i]];
    	int ans=0x3f3f3f3f;
    	rep(i,1,sp){
    		int j=i;
    		while(ss[j]-ss[i]<=s&&j<=sp){
    			int tmp=max(maxd,max(ss[i],tt[j]));
    			cmin(ans,tmp);
    			++j;
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    /*
    5 2
    1 2 5
    2 3 2
    2 4 4
    2 5 3
    
    ans=5;
    */
    
  • 相关阅读:
    maven安装
    删掉centos原有的openjdk并安装sun jdk
    搭建私有仓库Harbor
    什么是Docker
    总结docker常用命令
    MySQL如何修改密码
    VMware vSphere
    安装Esxi 6.5
    Linux安装python3.6
    提高Linux运维效率的30个命令行常用快捷键
  • 原文地址:https://www.cnblogs.com/hangzz/p/13377809.html
Copyright © 2011-2022 走看看