suill_ 2024-07-18 22:06 采纳率: 37.5%
浏览 3
已结题

为什么我输出的val数组都为0?(语言-c++)

为什么我经过dfs后输出的val数组都为0?

//kruska找最大生成树(保证所经过权值最大)的最小边
#include<bits/stdc++.h>
using namespace std;
#define N 20100
#define ll long long
struct node
{
    int v,u,w;
}e[N];
struct leaf
{
    int u,v,w; 
}tr[N*2];
int cnt=0,n,m,q;
int h[N],par[N],dis[N];
int dep[N],st[N][20],val[N];//lca
bool cmp(node a,node b)//排序的比较都是bool
{
    return a.w>b.w;
}
void add(int u,int v,int w)
{
    cnt++;
    tr[cnt].v=v;
    tr[cnt].w=w;
    tr[cnt].u=h[u];
    h[u]=cnt;
}
void init(int n)
{
    for(int i=1;i<=n;i++)
        par[i]=i;
}
int find(int x)
{
    if(x==par[x])
        return par[x];
    else
    {
        par[x]=find(par[x]);
        return par[x];
    }
}
void kruskal()
{
    sort(e+1,e+n+1,cmp);
    init(2*n);//双向边
    for(int i=1;i<=m;i++)
    {
        int fx=find(e[i].u);
        int fy=find(e[i].v);
        if(fx^fy)
        {
            par[fx]=par[fy];
            add(e[i].u,e[i].v,e[i].w);
            add(e[i].v,e[i].u,e[i].w);
        }
    }
}
void dfs(int x,int f)
{
    dep[x]=dep[f]+1;
    for(int i=1;1<<i<=dep[x];i++)
        st[x][i]=st[st[x][i-1]][i-1];
    for(int i=h[x];i;i=tr[i].u)
    {
        int v=e[i].v;
        if(v!=f)
        {
            val[v]=tr[i].w;
            st[v][0]=x;
            dfs(v,x);
        }
    }
}
int lca(int a,int b)
{
    if(find(a)!=find(b))
        return -1;
    if(find(a)!=find(b))
        return -1;//两个节点不联通
    if(dep[a]<dep[b])
        swap(a,b);
    while(dep[a]>dep[b])
    {
        int k=log2(dep[a]-dep[b]);
        a=st[a][k];
    }
    if(a==b)
        return a;
    for(int i=log2(dep[a])+1;i>=0;i--)
    {
        if(st[a][i]==st[b][i])
        {
            a=st[a][i];
            b=st[a][i];
        }
    }
    return st[a][0];
}
void work(int x,int y)
{
    int fa=lca(x,y);
    if(fa==-1)
        cout<<-1<<"\n";return;
    int a,b;
    a=b=0x3f3f3f3f;
    for(int i=x;i!=fa;i=st[x][0])
        a=min(a,val[i]);
    for(int i=x;i!=fa;i=st[x][0])
        b=min(b,val[i]);
    cout<<min(a,b)<<"\n";
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        cin>>e[i].u>>e[i].v>>e[i].w;
    kruskal();
    cin>>q;
    dep[1]=1;
    for(int i=1;i<=n;i++)
    {
        if(find(i)==i)//i为树根
        {
            st[i][0]=i;
            dfs(i,0);//因为可能有多棵树,所以for循环枚举一遍
        }
    }//初始化!!!
    for(int i=1;i<=n;i++)
        cout<<val[i]<<" ";
    // while(q--)
    // {
    //     int a,b;
    //     cin>>a>>b;
    //     work(a,b);//最小边一定在两点路径到lca上 
    // }
    return 0;
}
  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2024-07-18 22:06
    关注

    以下内容由AIGC及阿里嘎多学长共同生成、有用望采纳:


    让我们逐步分析你的代码,并解决你提出的问题。

    1. 为什么经过深度优先搜索(DFS)后输出的val数组都为0?

    在你的代码中,val数组的赋值逻辑存在问题。具体来说,val数组的赋值发生在dfs函数中,但是dfs函数的调用时机和逻辑可能不正确。以下是关键部分的代码:

    void dfs(int x,int f)
    {
        dep[x]=dep[f]+1;
        for(int i=1;1<<i<=dep[x];i++)
            st[x][i]=st[st[x][i-1]][i-1];
        for(int i=h[x];i;i=tr[i].u)
        {
            int v=tr[i].v;
            if(v!=f)
            {
                val[v]=tr[i].w;
                st[v][0]=x;
                dfs(v,x);
            }
        }
    }
    

    问题在于,dfs函数的调用时机不正确。你需要在Kruskal算法完成后,确保每个节点都是树的一部分时,再调用dfs函数。你的代码中,dfs函数的调用在初始化dep[1]=1之后,但实际上应该在Kruskal算法完成后调用。

    2. 如何确保val数组在DFS过程中正确赋值?

    你需要确保在Kruskal算法完成后,调用dfs函数。以下是修改后的代码:

    void kruskal()
    {
        sort(e+1,e+n+1,cmp);
        init(2*n);
        for(int i=1;i<=m;i++)
        {
            int fx=find(e[i].u);
            int fy=find(e[i].v);
            if(fx^fy)
            {
                par[fx]=par[fy];
                add(e[i].u,e[i].v,e[i].w);
                add(e[i].v,e[i].u,e[i].w);
            }
        }
    }
    
    void dfs(int x, int f)
    {
        dep[x] = dep[f] + 1;
        for (int i = 1; 1 << i <= dep[x]; i++)
            st[x][i] = st[st[x][i - 1]][i - 1];
        for (int i = h[x]; i; i = tr[i].u)
        {
            int v = tr[i].v;
            if (v != f)
            {
                val[v] = tr[i].w;
                st[v][0] = x;
                dfs(v, x);
            }
        }
    }
    
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
            cin >> e[i].u >> e[i].v >> e[i].w;
        kruskal();
        cin >> q;
        for (int i = 1; i <= n; i++)
        {
            if (find(i) == i) // i为树根
            {
                st[i][0] = i;
                dfs(i, 0); // 因为可能有多棵树,所以for循环枚举一遍
            }
        }
        for (int i = 1; i <= n; i++)
            cout << val[i] << " ";
        return 0;
    }
    

    3. 如何正确初始化和使用st数组?

    在你的代码中,st数组的初始化和使用是正确的。st数组用于存储每个节点的祖先节点信息,通过在DFS过程中更新st数组的值来实现。

    4. 如何正确实现最小生成树的Kruskal算法?

    你的Kruskal算法实现是正确的,关键在于确保边的排序和并查集的合并逻辑正确。

    5. 如何正确实现LCA(最近公共祖先)算法?

    你的LCA算法实现也是正确的,关键在于使用深度优先搜索来初始化LCA的st数组,并在查询LCA时使用路径压缩来优化查询时间。

    6. 如何正确实现work函数来输出两点间的最小边?

    你的work函数的实现逻辑是正确的,关键在于先找到两点的LCA,然后沿着从两点到LCA的路径,找到路径上的最小边。

    通过以上修改,你的代码应该能够正确运行并输出预期的结果。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月26日
  • 创建了问题 7月18日

悬赏问题

  • ¥15 elementui上传结合oss接口断点续传,现在只差停止上传和继续上传,各大精英看下
  • ¥100 单片机hardfaulr
  • ¥20 手机截图相片分辨率降低一半
  • ¥50 求一段sql语句,遇到小难题了,可以50米解决
  • ¥15 速求,对多种商品的购买力优化问题(用遗传算法、枚举法、粒子群算法、模拟退火算法等方法求解)
  • ¥100 速求!商品购买力最优化问题(用遗传算法求解,给出python代码)
  • ¥15 虚拟机检测,可以是封装好的DLL,可付费
  • ¥15 kafka无法正常启动(只启动了一瞬间会然后挂了)
  • ¥15 Workbench中材料库无法更新,如何解决?
  • ¥20 如何推断此服务器配置