bzoj3124 [Sdoi2013]直径 直径+树形dp

这个题标签为什么会有网络流。。

首先树的直径求法就是两遍dfs

然后以其中一个为树的根,统计子树到节点的最长距离与次长距离:


符合条件的点一定是最长距离唯一的,且次长距离与到根的距离不相等


注:

1、同级语句的顺序

2、long long


码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 500000
int hou[N],tot,xia[N],a,b,c,fu[N],zhong[N],id[N],ans,n,m,i,j;
long long v[N],d[N],d2[N],maxx;
void jian(int a,int b,long long c)
{
	++tot;hou[tot]=xia[a];xia[a]=tot;zhong[tot]=b;v[tot]=c;	
}
void jia(int a,int b,long long c)
{
		jian(a,b,c);jian(b,a,c);
}
void dfs(int o,int fa)
{
int i;
d[o]=0;
id[o]=o;
for(i=xia[o];i!=0;i=hou[i])
{
int nd=zhong[i];
if(nd==fa)continue;
dfs(nd,o);
if(d[nd]+v[i]>d[o])d[o]=d[nd]+v[i],id[o]=id[nd];
}	
} 
void dp(int o,int fa)
{
	int i;
	fu[o]=fa;
	id[o]=0;
	for(i=xia[o];i!=-1;i=hou[i])
	{
		int nd=zhong[i];
		if(nd==fa)continue;
		dp(nd,o);
		if(d[nd]+v[i]==d[o])
		{
			id[o]=1;
		}else 
		if(d[nd]+v[i]>d[o])
		{
			id[o]=0;
			d2[o]=d[o];
			d[o]=d[nd]+v[i];
		}else 	
		if(d[nd]+v[i]>d2[o])
		d2[o]=d[nd];
	}
}
int main()
{   memset(xia,-1,sizeof(xia));
	scanf("%d",&n);
	for(i=1;i<n;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		jia(a,b,c);		
	}
	dfs(1,0);
	int st=id[1];
	dfs(st,0);
	int nd=id[st];
	maxx=d[st];
	printf("%lld\n",maxx);
	memset(d,0,sizeof(d));
	dp(st,0);
	int o=nd,ans=0;
	while(o)
	{//cout<<o;
		if(id[o]==1&&d2[o]==maxx-d[o])
		{
			ans=0;
			break;
		}
				if(d2[o]==maxx-d[o])
		{
		break;
		}
				if(id[o]==0)
		{
			++ans;
		}
		if(id[o]==1)
		{
			ans=1;
		}
		o=fu[o];
	}
	if(o==st)ans--;
	printf("%d",ans);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值