zoukankan      html  css  js  c++  java
  • CF14E Camels

    (暑假的CF模拟赛)

    这是我感觉最难的题

    一开始以为要先跑一遍树的直径,然后在剩下可以选的点里跑最长的。

    经过几分钟沉思后发现这方法不对……

    例如:

    考虑换一种方法,枚举一个断边,将原树分开的两子树分别跑直径,然后直径相乘就可以求出答案。

    (求直径我写的dp,赛事遗忘bfs求直径如何打)

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    long long head[305],ans,a,b,fk;
    struct hehe
    {
    	long long w,syg;
    }lsqxx[605];
    void add(long long t,long long w)
    {
    	ans++;
    	lsqxx[ans].w=w;
    	lsqxx[ans].syg=head[t];
    	head[t]=ans;
    }
    long long n,zc;
    long long zj(long long wz,long long bb)//求直径函数 
    {
    	long long daan=0,cd1=0,cd2=0;//cd1,cd2分别代表子树中深的最大值和次大值 
    	for(int i=head[wz];i!=0;i=lsqxx[i].syg)
    	{
    		if(lsqxx[i].w==bb)
    		{
    			continue;
    		}
    		daan=max(daan,zj(lsqxx[i].w,wz));//具体思想,zc为向下搜后的最大值,如果比现在的最大值大,就替换,现在的次大值变为之前的最大值 
    		if(zc>cd1)
    		{
    			cd2=cd1;
    			cd1=zc;
    		}else
    		{
    			cd2=max(cd2,zc);//如果zc没最大值大,就看看能否替换次大值 
    		}
    	}
    	daan=max(daan,cd1+cd2);//然后就可以求出直径 
    	zc=cd1+1;
    	return daan;
    }
    int main()
    {
    	scanf("%lld",&n);
    	for(int i=1;i<n;i++)
    	{
    		scanf("%lld%lld",&a,&b);
    		add(a,b);
    		add(b,a);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=head[i];j!=0;j=lsqxx[j].syg)//断边 
    		{
    			zc=0;
    			long long aa=zj(i,lsqxx[j].w);
    			zc=0;
    			long long aaa=zj(lsqxx[j].w,i);
    			fk=max(fk,aa*aaa);
    		}
    	}
    	printf("%lld
    ",fk);
    	return 0;
    }
    

      

  • 相关阅读:
    PHP 获取完整URL地址
    竖向 两级手风琴 TAB 栏
    Log4Net 用法记录
    C# 正整数和非零正整数校验
    NewtonSoft对象转json时,把 NULL 转 "" , 过滤 NULL, DateTime 时间类型去除 T
    SQL 事务
    SQL insert 主键冲突
    【记录】无法读取配置节“AppSettings”,因为它缺少节声明
    asp.net 前后台数据交互方式(转)
    php 生成文件txt到指定目录
  • 原文地址:https://www.cnblogs.com/lichangjian/p/14989644.html
Copyright © 2011-2022 走看看