【无标题】

https://www.dotcpp.com/oj/problem3156.html

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define INF 0x3f3f3f3f3f3f3f3f

const int N =1e5+5;

int dep[N],f[N][50],dis[N],luxian[N]; 

struct edge{
	int u;
	int v;
	int d;
};

vector<edge>e[N];
int n,k;

void dfs(int u,int fa,int d)
{
	dep[u]=dep[fa]+1;	// 记录深度 
	dis[u]=d;
	f[u][0]=fa;	//ST表 
	//初始化ST表 
	for (int i=1;(1<<i) <= dep[u];++i)	
	{
		f[u][i]=f[f[u][i-1]][i-1];
	}
	for (int i=0;i<e[u].size();++i )
	{
		edge v=e[u][i];
		if (v.v == fa) continue;
		dfs(v.v,u,v.d+dis[u]);
	}
}

int lca(int x,int y)
{
	//保证x在y的下面 
	if (dep[x]< dep[y]) swap(x,y);
	//向上跳,直到x的深度和y相同,然后再一起找共同祖先,如果x==y了,那么共同祖先就是x 
	for (int i=__lg(n);i>=0;--i)
	{
		if (dep[f[x][i]] >= dep[y]) x=f[x][i];
		if (x==y) return x; 
 	}
 	//到了同一深度之后,就开始一起向上跳 
 	for (int i=__lg(n);i>=0;--i)
 	{
 		if (f[x][i]!=f[y][i])
		{
			x=f[x][i];
			y=f[y][i];
		}
	}
 	return f[x][0];
}

int get(int x ,int y)
{
	return dis[x]+dis[y]-dis[lca(x,y)]*2;
}

signed main()
{
	cin>>n>>k;
	for (int i=0;i<n-1; ++i)
	{
		int u,v,d;
		cin>>u>>v>>d;
		e[u].push_back({u,v,d});
		e[v].push_back({v,u,d});
	}
	for (int i=1;i<=k;++i)
	{
		cin>>luxian[i];
	}
	dfs(1,0,0);
	int sum=0;
	for (int i=1;i<k;++i)
	{
		sum+=get(luxian[i],luxian[i+1]);
	}
	for (int i=1;i<=k;++i)
	{
		int ans=sum;
		//减掉路径的消耗 
		if (i!=1)	ans-=get(luxian[i],luxian[i-1]);
		if (i!=k) ans-=get(luxian[i],luxian[i+1]);
		if (i!=1 && i!=k) ans+=get(luxian[i-1],luxian[i+1]);
		cout<<ans<<" ";
	}
}

https://www.dotcpp.com/oj/problem3157.html

#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define INF 0x3f3f3f3f3f3f3f3f

const int N =1e5+5;

int dep[N],f[N][25],id[N],n,m,s[N]; 

struct edge{
	int id;
	int to;
};

vector<edge>e[N];

void dfs(int u,int fa)
{
	dep[u]=dep[fa]+1;
	f[u][0]=fa;
	for (int i=1;(1<<i) <= dep[u];++i)
	{
		f[u][i]=f[f[u][i-1]][i-1];
	}
	for (int i=0;i<e[u].size();++i)
	{
		edge v=e[u][i];
		if (v.to == fa) continue;
		dfs(v.to,u);
		id[v.to]=v.id;
	}
}

int lca(int x,int y)
{
	if (dep[x] < dep[y]) swap(x,y);
	while (dep[x] > dep[y])
	{
		x=f[x][__lg(dep[x] -dep[y] -1)];
	}
	if (x==y) return x;
 	for (int i=1 ; i<=20 ; ++i)
 	{
 		if (f[x][i] != f[y][i])
 		{
 			x=f[x][i];
			y=f[y][i];	
		}
	}
	return f[x][0];
}


//和LCA相比增加的部分---差分 
void add(int l,int r)
{
	s[l]++;
	s[r]++;
	s[lca(l,r)]-=2;
}

//计算子树和 
void cal_sum(int u,int fa)
{
	for (int i=0;i<e[u].size();++i)
	{
		edge v=e[u][i];
		if (v.to==fa) continue;
		cal_sum(v.to,u);
		s[u]+=s[v.to];
	}
}


signed main()
{
	cin>>n>>m;
	for (int i=1;i<n;++i)
	{
		int u,v;
		cin>>u>>v;
		e[u].push_back({i,v});
		e[v].push_back({i,u});
	}
	dfs(1,0);
	for (int i=0;i<m;++i)
	{
		int l;
		int r;
		cin>>l>>r;
		add(l,r);
	}
	cal_sum(1,0);
	int ans=0;
	for (int i=1;i<=n;++i)
	{
		if (s[i] == m && ans < id[i]) ans=id[i];
	}
	cout<<ans;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值