题意:
有一棵节点为 n 的树,树的每条边都有一个权值 w 。
每条边都有一个重要程度:等于这条边所分隔的两个集合的数量之积,再乘上这条边的权重。
问树的哪条边计算的值最大,输出这个最大值。
方法一:
dfs
思路:用邻接表建树。dfs后序遍历,枚举每条边计算的值,用 res 维护最大值。
关键点:去掉一条边后,一棵树就一分为二,变成两个连通块(即两个集合)
计算两个集合的数量之积即是求解的城市的对数,
最后再乘上这条边的权重即可。
并用 res 维护最大值。
#define ll long long
class Solution {
public:
ll res=0;
long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w) {
vector<vector<pair<int,int>>> g(n+1);
for(int i=0;i<n-1;i++){//建树
g[u[i]].push_back({v[i],w[i]});
g[v[i]].push_back({u[i],w[i]});
}
dfs(1,1,g,n);//从任意节点开始都行
return res;
}
int dfs(int x,int fa,vector<vector<pair<int,int>>> g,int n){
int sum=0;//记录以节点x为根节点的子树中节点数量
int num=g[x].size();
for(int i=0;i<num;i++){//遍历节点x的每条边
int y=g[x][i].first,z=g[x][i].second;
if(y!=fa){//如果未访问
int m=dfs(y,x,g,n);//得到节点x的各子树中的节点数量
sum+=m;
res=max(res,(ll)m*(n-m)*z);//维护最大值
}
}
return sum+1;
}
};
时间复杂度:
空间复杂度:![]()
方法二:
链式前向星存储
思路:同方法一的思路一致,方法一用邻接表存储,方法二用链式前向星存储边集。
优化了空间存储,使得空间复杂度从
#define ll long long
class Solution {
public:
ll res=0;
int e[200005],val[200005],ne[200005],h[100005];
int idx=0;
void add(int x,int y,int z){//添加边
e[idx]=y;
val[idx]=z;
ne[idx]=h[x];
h[x]=idx++;
}
long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w){
memset(h,-1,sizeof(h));
for(int i=0;i<n-1;i++){
add(u[i],v[i],w[i]);//无向图
add(v[i],u[i],w[i]);
}
dfs(1,1,n);
return res;
}
int dfs(int x,int fa,int n){
int sum=0;//记录以节点x为根节点的子树数量
for(int i=h[x];i!=-1;i=ne[i]){//遍历节点x的每条边
int y=e[i],z=val[i];
if(y!=fa){//如果未访问
int m=dfs(y,x,n);//得到节点x的各子树中的节点数量
sum+=m;
res=max(res,(ll)m*(n-m)*z);//维护最大值
}
}
return sum+1;
}
}; 时间复杂度:
空间复杂度:![]()



京公网安备 11010502036488号