C++ 查找树中两个节点之间的最大成本边 任务:

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

给定一个加权树图和一组节点对。对于集合中的每一对(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的支持?

我的尝试代码:
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;
}