树的直径之:【普通深搜+树形DP版本深搜】【树形DP版本树的直径的应用】【洛谷P3629】

 

 

 

/*
本题是让我们给原图加边:
加k条边,k条边(1,2) 

然后使得:
从黑点出发,遍历所有点,
然后再回到黑点 
然后新加的边,必须要经过 正好一次 
*/ 
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
const int M=2*N;
int e[M],ne[M],h[N],w[M],idx;
int dis[N];
int fa[N];
int f[N]; //把直径点做上标记 
int ans=0;

void add(int a,int b,int c)
{
	e[idx]=b;
	ne[idx]=h[a];
	w[idx]=c;
	h[a]=idx++;
}

void dfs(int u,int fath,int distance)
{
	dis[u]=distance;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(j==fath) continue;
		fa[j]=u;
		dfs(j,u,distance+w[i]);
	}
}

int dfs1(int u,int fa)
{
	int dist=0;
	int d1=0,d2=0;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(j==fa) continue;
		
		int d;
		int tt=dfs1(j,u);
		if(f[j]&&f[u])
		d=tt-w[i];
		else d=tt+w[i];
		 //①更新外部变量dist 
		dist=max(dist,d);
		//②更新外部变量d1和d2
		
		if(d>=d1)
		{
			d2=d1;
			d1=d;
		} 
		else if(d>d2)
		{
			d2=d;
		}
		
		//③更新全局变量 ans 
	
		ans=max(ans,d1+d2);
	}
	
	return dist;
} 


int main()
{
	int n,k;
	cin>>n>>k;
	
	memset(h,-1,sizeof h); 
	for(int i=0;i<n-1;i++)
	{
		int a,b;
		cin>>a>>b;
		
		add(a,b,1);
		add(b,a,1);
	}
	
	dfs(1,-1,0);
	
	int maxv=-0x3f3f3f3f;
	int start;
	for(int i=1;i<=n;i++)
	{
		if(maxv<dis[i])
		{
			maxv=dis[i];
			start=i;
		}
	}	
	
	
	dfs(start,-1,0);
	
	maxv=-0x3f3f3f3f;
	int end;
	for(int i=1;i<=n;i++)
	{
		if(maxv<dis[i])
		{
			maxv=dis[i];
			end=i;
		}
	}
	
	
	//maxv现在是最大直径了
	
	if(k==1)  //如果只要加一条边,那太香了
	{
		cout<<(n-1)*2-maxv+1<<endl;
		return 0;
	}
	
	//如果是加两条边,会比较麻烦一点
	//两条边,包含一条边的情况,所以我们先 存一条边的sum 
    int sum=(n-1)*2-maxv+1;
   // cout<<sum<<endl;
    
    /*然后再存另外讨论下一条边的情况
    把之前的直径点全部打上标记
	然后找一个新的两点之间的最远距离 
    */ 
    fa[start]=0;
    for(int i=end;i;i=fa[i]) //直径上的点打上标记  
    {
    	f[i]=1;
	}
	

	dfs1(1,-1);  //用一个新的树的直径的求法 (树形DP)法,因为此处有些点被标记掉了不能用 
	 
	cout<<sum-ans+1<<endl;
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值