C++ 查找树中两个节点之间的最大成本边 任务:
给定一个加权树图和一组节点对。对于集合中的每一对(u,v),我需要(有效地)找到(u,v)之间的最大边 我的做法: 对每对(u,v)使用Tarjan算法,我们可以找到最低的共同祖先LCA(u,v)=a。然后我们可以将(u,v)之间的路径表示为(u,a)和(v,a)路径的并集,将(u,v)之间的最大边表示为max(max_边(u,a),max_边(v,a)) 问题: 我正在尝试在LCA算法中添加max_edge save,但尚未获得任何成功 问题是:如何在LCA Tarjan算法中添加对max edge save的支持? 我的尝试代码:C++ 查找树中两个节点之间的最大成本边 任务:,c++,algorithm,graph,tree,disjoint-sets,C++,Algorithm,Graph,Tree,Disjoint Sets,给定一个加权树图和一组节点对。对于集合中的每一对(u,v),我需要(有效地)找到(u,v)之间的最大边 我的做法: 对每对(u,v)使用Tarjan算法,我们可以找到最低的共同祖先LCA(u,v)=a。然后我们可以将(u,v)之间的路径表示为(u,a)和(v,a)路径的并集,将(u,v)之间的最大边表示为max(max_边(u,a),max_边(v,a)) 问题: 我正在尝试在LCA算法中添加max_edge save,但尚未获得任何成功 问题是:如何在LCA Tarjan算法中添加对max e
int最大成本;
int dsu_find(int节点)
{
如果(节点==父节点[节点])
返回节点;
max_cost=std::max(max_cost,边[节点][父节点]];
返回父[节点]=dsu_find(父[节点]);
}
无效lca_dfs(int节点,std::vector和query_列表)
{
dsu_make(节点);
祖先[节点]=节点;
标记[节点]=真;
for(自动邻居:邻接列表[节点])
{
如果(!标记[邻居。第一个])
{
lca_dfs(邻居。首先,查询_列表);
dsu_unite(节点,邻居,第一);
祖先[dsu_find(node)]=节点;
}
}
for(自动查询节点:查询列表[节点])
if(标记[查询节点])
{
dsu_查找(查询_节点);
dsu_查找(节点);
printf(“%d%d->%lld\n”,节点,查询节点,最大成本);
查询列表[查询节点]。删除(节点);
最大成本=0;
}
}
但它工作不正确
我的完整生命周期评价实施(无错误修改):
std::向量父代;
std::向量秩;
std::载体祖先;
向量标记;
std::向量邻接列表;
无效lca_dfs(int节点,std::vector和query_列表)
{
dsu_make(节点);
祖先[节点]=节点;
标记[节点]=真;
for(自动邻居:邻接列表[节点])
{
如果(!标记[邻居。第一个])
{
lca_dfs(邻居。首先,查询_列表);
dsu_unite(节点,邻居,第一);
祖先[dsu_find(node)]=节点;
}
}
for(自动查询节点:查询列表[节点])
if(标记[查询节点])
{
printf(“%d%d的LCA是%d\n”,节点,查询节点,祖先[dsu\U查找(查询节点)];
查询列表[查询节点]。删除(节点);
}
}
//dsu操作
无效dsu_make(内部节点)
{
父[节点]=节点;
秩[节点]=0;
}
int dsu_find(int节点)
{
返回节点==parent[node]?节点:parent[node]=dsu_find(parent[node]);
}
无效dsu_unite(内部节点_1,内部节点_2)
{
int root_1=dsu_-find(节点_1),root_2=dsu-find(节点_2);
if(root_1!=root_2)
{
if(秩[root\u 1]<秩[root\u 2])
交换(根目录1,根目录2);
父[root_2]=root_1;
if(秩[root\u 1]==秩[root\u 2])
秩[根_1]++;
}
}
*对于每个节点,查询_列表[node]由v组成,例如需要(node,v)对。
我明白,我使用双内存(只是为了更容易访问)
对于任何提示或实现修复,我将不胜感激。希望此实现对您有效。
Hope this Implementation works for you.
#include <bits/stdc++.h>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ass 1e18
#define MOD 1000000007
#define mp make_pair
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define fi first
#define se second
#define sz(x) (ll)x.size()
#define present(c,x) ((c).find(x) != (c).end())
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define debug(x) cout << #x << ": " << x << endl;
#define debug2(x,y) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<< endl;
#define debug3(x,y,z) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<<" "<<#z<<" : "<<z<< endl;
using namespace std;
typedef long long int ll;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
pair<int,int> parent[200005],par[200005],dpp[200005][19];
vector<pair< pair<int,int>,pair<int,int> > >v;
vector<pair<int,int> >vv[200005];
int level[200005],vis[200005];
ll ans[200005];
void dfs(int x,int p)
{
level[x]=level[p]+1;
for(int i=0;i<sz(vv[x]);i++)
{
if(vv[x][i].fi!=p)
{
par[vv[x][i].fi].fi=x;
par[vv[x][i].fi].se=vv[x][i].se;
dfs(vv[x][i].fi,x);
}
}
}
void computeparent(int n)
{
for(int i=1;i<=n;i++)
dpp[i][0]=par[i];
for(int j=1;j<=18;j++)
{
for(int i=1;i<=n;i++)
{
dpp[i][j].fi=dpp[dpp[i][j-1].fi][j-1].fi;
dpp[i][j].se=max(dpp[i][j-1].se,dpp[dpp[i][j-1].fi][j-1].se);
}
}
}
int lca(int a,int b)
{
if(level[b]>level[a])
swap(a,b);
int diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
a=dpp[a][i].fi;
}
if(a==b)
return a;
for(int i=m;i>=0;i--)
{
if(dpp[a][i].fi!=dpp[b][i].fi)
{
a=dpp[a][i].fi;
b=dpp[b][i].fi;
}
}
return dpp[a][0].fi;
}
int lca2(int a,int b)
{
int c=a,d=b;
if(level[b]>level[a])
swap(a,b);
int i,maxi=0,diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
{
maxi=max(maxi,dpp[a][i].se);
a=dpp[a][i].fi;
}
}
return maxi;
}
int finds(int a)
{
while(parent[a].fi!=a)
{
a=parent[a].fi;
}
return a;
}
void unions(int x,int y)
{
if(parent[x].se>parent[y].se)
parent[y].fi=x;
else if(parent[x].se<parent[y].se)
parent[x].fi=y;
else
{
parent[x].fi=y;
parent[x].se++;
}
}
void solve()
{
ll sum=0;
int n,m,i,a,b,c;
cin>>n>>m;
for(i=1;i<=n;i++)
{
parent[i].fi=i;
parent[i].se=0;
}
for(i=0;i<m;i++)
{
cin>>a>>b>>c;
v.pb(mp(mp(c,i),mp(a,b)));
}
sort(v.begin(),v.end());
for(i=0;i<sz(v);i++)
{
int a=v[i].se.fi,b=v[i].se.se;
int x=finds(a),y=finds(b);
if(x!=y)
{
vv[a].pb(mp(b,v[i].fi.fi));
vv[b].pb(mp(a,v[i].fi.fi));
ans[v[i].fi.se]=1;
unions(x,y);
sum+=v[i].fi.fi;
}
}
dfs(1,0);
computeparent(n);
for(i=0;i<m;i++)
{
if(ans[v[i].fi.se]==0)
{
int a=lca(v[i].se.fi,v[i].se.se);
ans[v[i].fi.se]=sum+v[i].fi.fi-max(lca2(a,v[i].se.fi),lca2(a,v[i].se.se));
}
else
ans[v[i].fi.se]=sum;
}
for(i=0;i<m;i++)
cout<<ans[i]<<"\n";
}
int main()
{
boost
int t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}
#包括
#包括
#包括
#包括
#定义ass 1e18
#定义MOD 100000007
#定义mp make_对
#定义pb推回
#定义pf push_front
#定义pob pop_back
#定义pof pop_front
#首先定义fi
#定义se秒
#定义sz(x)(ll)x.size()
#定义现在(c,x)((c.find(x)!=(c.end())
#定义boost ios_base::sync_with_stdio(false);cin.tie(空);
#定义调试(x)为什么不修改Dijkstra的算法,使其遵循最大加权边而不是最小加权边?Dijkstra的似乎是这个问题的最佳选择。目前还不清楚u和v之间的最大边是如何定义的。我的理解是:取所有边{u,v},然后选择一条权重最大的边。但这可能不是您想要的。可能的副本请包括您在回答问题时如何得出解决方案的描述。在@SamKing的评论中添加内容,请在回答下一个问题之前仔细阅读@取样逻辑和问题中给出的相同。我只分享了我的方法。
std::vector<int> parent;
std::vector<int> rank;
std::vector<int> ancestor;
std::vector<bool> marks;
std::vector<std::list<std::pair<int, long long>>> adjacency_list;
void lca_dfs(int node, std::vector<std::list<int>> &query_list)
{
dsu_make(node);
ancestor[node] = node;
marks[node] = true;
for(auto neighbour:adjacency_list[node])
{
if (!marks[neighbour.first])
{
lca_dfs(neighbour.first,query_list);
dsu_unite(node, neighbour.first);
ancestor[dsu_find(node)] = node;
}
}
for (auto query_node : query_list[node])
if (marks[query_node])
{
printf("LCA of %d %d is %d\n", node, query_node,ancestor[dsu_find(query_node)]);
query_list[query_node].remove(node);
}
}
//dsu operations
void dsu_make(int node)
{
parent[node] = node;
rank[node] = 0;
}
int dsu_find(int node)
{
return node == parent[node] ? node : parent[node]=dsu_find(parent[node]);
}
void dsu_unite(int node_1,int node_2)
{
int root_1 = dsu_find(node_1), root_2 = dsu_find(node_2);
if(root_1!=root_2)
{
if(rank[root_1] < rank[root_2])
std::swap(root_1, root_2);
parent[root_2] = root_1;
if (rank[root_1] == rank[root_2])
rank[root_1]++;
}
}
Hope this Implementation works for you.
#include <bits/stdc++.h>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ass 1e18
#define MOD 1000000007
#define mp make_pair
#define pb push_back
#define pf push_front
#define pob pop_back
#define pof pop_front
#define fi first
#define se second
#define sz(x) (ll)x.size()
#define present(c,x) ((c).find(x) != (c).end())
#define boost ios_base::sync_with_stdio(false);cin.tie(NULL);
#define debug(x) cout << #x << ": " << x << endl;
#define debug2(x,y) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<< endl;
#define debug3(x,y,z) cout<<#x<<": "<< x<< ", "<< #y<< ": "<< y<<" "<<#z<<" : "<<z<< endl;
using namespace std;
typedef long long int ll;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
pair<int,int> parent[200005],par[200005],dpp[200005][19];
vector<pair< pair<int,int>,pair<int,int> > >v;
vector<pair<int,int> >vv[200005];
int level[200005],vis[200005];
ll ans[200005];
void dfs(int x,int p)
{
level[x]=level[p]+1;
for(int i=0;i<sz(vv[x]);i++)
{
if(vv[x][i].fi!=p)
{
par[vv[x][i].fi].fi=x;
par[vv[x][i].fi].se=vv[x][i].se;
dfs(vv[x][i].fi,x);
}
}
}
void computeparent(int n)
{
for(int i=1;i<=n;i++)
dpp[i][0]=par[i];
for(int j=1;j<=18;j++)
{
for(int i=1;i<=n;i++)
{
dpp[i][j].fi=dpp[dpp[i][j-1].fi][j-1].fi;
dpp[i][j].se=max(dpp[i][j-1].se,dpp[dpp[i][j-1].fi][j-1].se);
}
}
}
int lca(int a,int b)
{
if(level[b]>level[a])
swap(a,b);
int diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
a=dpp[a][i].fi;
}
if(a==b)
return a;
for(int i=m;i>=0;i--)
{
if(dpp[a][i].fi!=dpp[b][i].fi)
{
a=dpp[a][i].fi;
b=dpp[b][i].fi;
}
}
return dpp[a][0].fi;
}
int lca2(int a,int b)
{
int c=a,d=b;
if(level[b]>level[a])
swap(a,b);
int i,maxi=0,diff=level[a]-level[b];
int m=ceil(log2(diff));
for(int i=m;i>=0;i--)
{
if(diff&(1LL<<i))
{
maxi=max(maxi,dpp[a][i].se);
a=dpp[a][i].fi;
}
}
return maxi;
}
int finds(int a)
{
while(parent[a].fi!=a)
{
a=parent[a].fi;
}
return a;
}
void unions(int x,int y)
{
if(parent[x].se>parent[y].se)
parent[y].fi=x;
else if(parent[x].se<parent[y].se)
parent[x].fi=y;
else
{
parent[x].fi=y;
parent[x].se++;
}
}
void solve()
{
ll sum=0;
int n,m,i,a,b,c;
cin>>n>>m;
for(i=1;i<=n;i++)
{
parent[i].fi=i;
parent[i].se=0;
}
for(i=0;i<m;i++)
{
cin>>a>>b>>c;
v.pb(mp(mp(c,i),mp(a,b)));
}
sort(v.begin(),v.end());
for(i=0;i<sz(v);i++)
{
int a=v[i].se.fi,b=v[i].se.se;
int x=finds(a),y=finds(b);
if(x!=y)
{
vv[a].pb(mp(b,v[i].fi.fi));
vv[b].pb(mp(a,v[i].fi.fi));
ans[v[i].fi.se]=1;
unions(x,y);
sum+=v[i].fi.fi;
}
}
dfs(1,0);
computeparent(n);
for(i=0;i<m;i++)
{
if(ans[v[i].fi.se]==0)
{
int a=lca(v[i].se.fi,v[i].se.se);
ans[v[i].fi.se]=sum+v[i].fi.fi-max(lca2(a,v[i].se.fi),lca2(a,v[i].se.se));
}
else
ans[v[i].fi.se]=sum;
}
for(i=0;i<m;i++)
cout<<ans[i]<<"\n";
}
int main()
{
boost
int t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}