一、“换边”算法

用Kruskal求最小生成树,标记用过的边。求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就是次小的生成树。可以证明:最小生成树与次小生成树之间仅有一条边不同。

这样相当于运行m次Kruskal算法。

复杂度O(m^2)

示例代码:

int Kruskal_MinTree()
{
    int u,v;
    init();
    int i,flag,cnt;
    minedge = 0;
    flag = cnt = 0;
    int tmp = 0;
    for(i=0;i<m;i++)
    {
        u = edge[i].s;
        v = edge[i].t;
        int fx = findset(u);
        int fy = findset(v);
        if(fx != fy)
        {
            use[minedge++] = i;
            tmp += edge[i].w;
            fa[fx] = fy;
            cnt++;
        }
        if(cnt == n-1)
        {
            flag = 1;   //找到最小生成树
            break;
        }
    }
    if(flag)
        return tmp;
    return -1;   //不存在最小生成树,返回-1
}

int Sec_MinTree()
{
    int i,j,mini,tmp;
    int cnt,flag,u,v;
    mini = Mod;
    for(i=0;i<minedge;i++)   //枚举最小生成树中的每条边,将其去除
    {
        init();
        flag = cnt = tmp = 0;
        for(j=0;j<m;j++)
        {
            if(j != use[i])  //去除边
            {
                u = edge[j].s;
                v = edge[j].t;
                int fx = findset(u);
                int fy = findset(v);
                if(fx != fy)
                {
                    cnt++;
                    tmp += edge[j].w;
                    fa[fx] = fy;
                }
                if(cnt == n-1)
                {
                    flag = 1;
                    break;
                }
            }
        }
        if(flag && tmp < mini)
            mini = tmp;
    }
    if(mini == Mod)
        mini = -1;
    return mini;
}
View Code

相关文章:

  • 2021-05-09
  • 2021-06-13
  • 2022-12-23
  • 2021-07-23
  • 2021-12-02
猜你喜欢
  • 2022-12-23
  • 2021-08-05
  • 2021-11-26
  • 2021-06-05
  • 2022-12-23
  • 2021-05-28
  • 2021-08-01
相关资源
相似解决方案