• [TJOI2017]城市 树形dp


    https://www.luogu.com.cn/problem/P3761

    这是个神仙题,会卡常

    题目让你改一条边把直径变得最短。

    枚举每条边,会把图分成两个地方,两个连通块(x区和y区域)都换根dp一下,算出离x最远的点的距离记为dis【x】。然后枚举一下

     新直径有三个来源   1 max dis[x]x里面最大的   ,2 dis[y]y里面最大的  ,3 ,min(dis[x] + dis[y] + len)

    具体看代码吧,不能用vector会卡常QAQ

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    using namespace std;
    const int maxn = 5050+11;
    typedef long long ll;
    
    struct Node{
    	int p;
    	ll len;
    	int next;
    }G[maxn*3];
    
    int head[maxn];
    int cnt = 0;
    int n;
    void add(int x,int y,ll len){
    	G[++cnt].p = y;
    	G[cnt].len = len;
    	G[cnt].next = head[x]; 
    	head[x] = cnt;
    }
    
     
    ll dp[maxn],dp2[maxn];
    
    int cal(int x,ll val){
    	if(val >= dp[x]){
    		dp2[x] = dp[x];
    		dp[x] = val;
    	}
    	else{
    		if(val >= dp2[x]){
    			dp2[x] = val;
    		}
    	}
    	return 0;
    }
    
    
    int dfs(int x,int fa){
    	dp[x] = dp2[x] = 0;
    	for(int i=head[x];i;i = G[i].next){
    		int p = G[i].p;
    		ll len = G[i].len;
    		if(p == fa) continue;
    		dfs(p,x);
    		cal(x,dp[p]+len); 
    	}
    	return 0;
    }
    ll cns = 1e15;
    ll dd;
    
    int dfs2(int x,int fa){
    	dd = max(dd,dp[x]);
    	cns = min(cns,dp[x]);
    	for(int i=head[x];i;i = G[i].next){
    		int p = G[i].p;
    		ll len = G[i].len;
    		if(p == fa) continue;
    		if(dp[p] + len == dp[x]){
    			cal(p,dp2[x]+len);
    		}
    		else{
    			cal(p,dp[x]+len);
    		}
    		dfs2(p,x);
    	}
    	
    	return 0;
    }
    
    int main(){
    	scanf("%d",&n);
    	int x,y;
    	for(int i=1;i<n;i++){
    		int x,y;
    		ll len;
    		scanf("%d %d %lld",&x,&y,&len);
    		add(x,y,len);
    		add(y,x,len);
    	}
    	
    	
    	ll ans = 1e16;
    	for(int i=1;i<=n;i++){
    		for(int j=head[i];j;j = G[j].next){
    		//	cout<<i<<" "<<G[j].p<<endl;
    			int be = i;
    			int en = G[j].p;
    			ll len = G[j].len;
    			if(len > ans) continue;
    			if(be > en) continue;
    			cns = 1e15;
    			dd = 0;
    			dfs(be,en);
    			dfs2(be,en);
    			ll a = cns;
    			if(dd > ans || cns + len > ans) continue;
    			
    			cns = 1e15;
    			dfs(en,be);
    			dfs2(en,be);
    	
    			dd = max(dd,cns + a + len);
    			ans = min(dd,ans);
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    第一次作业-准备篇
    个人作业——软件工程实践总结
    团队作业第二次—项目选题报告
    软工实践第三次作业(结对第二次作业)
    软工实践第二次作业(结对第一次作业)
    第一次作业-准备篇
    软工实践|个人作业——软件工程实践总结作业
    软工实践|团队作业第二次—项目选题报告
    软工实践|结对第二次—文献摘要热词统计及进阶需求
    软工实践|结对第一次—原型设计(文献摘要热词统计)
  • 原文地址:https://www.cnblogs.com/lesning/p/13684372.html
Copyright © 2020-2023  润新知