セカンダリ生成ツリーprimとkruskal


prim:まずprimで最小生成ツリーTを求め、primと同時に、Tに任意の2点u,vを結ぶ唯一の路の中で重み値が最大の辺の重み値を1つのマトリクスmaxd[u][v]で記録することは容易である.primはノードとその親ノードを1つ増加するたびに、DPを採用すると、最大重み値は新たに加わった辺であるか、親ノードから開始点までのDPで算出される距離であるか.すなわち、maxd[j][p]=max[p][j]=lowc[p]>max[j][closest[p]?lowc[p] : max[j][closest[p]] ; Tにないすべてのエッジuvを列挙し,エッジuvを加えると必ずmaxd[u][v]のエッジに置き換えられ,これによりセカンダリが保証される.
const int INF=0x3f3f3f3f;
const int MAXN=110;
bool vis[MAXN],used[MAXN][MAXN];
int lowc[MAXN],closest[MAXN],maxd[MAXN][MAXN];
int Prim(int cost[][MAXN],int n)//  0~n-1
{
    int ans=0;
    memset(vis,false,sizeof(vis));
    vis[0]=true;
    lowc[0]=0;
    for(int i=1; i
    {
        lowc[i]=cost[0][i];//         
        closest[i]=1;
    }
    for(int i=1; i
    {
        int minc=INF;
        int p=-1;
        for(int j=0; j
            if(!vis[j]&&minc>lowc[j])
            {
                minc=lowc[j];
                p=j;
            }
        if(minc==INF)return -1;//     
        ans+=minc;
        vis[p]=true;//p    
        used[p][closest[p]]=used[closest[p]][p]=true;
        for(int j=0; j
        {
            ///  
            if(vis[j]&&j!=p)
            {
                maxd[j][p] = maxd[p][j] = lowc[p] > maxd[j][closest[p]] ? lowc[p] : maxd[j][closest[p]] ;
            }
            if(!vis[j]&&lowc[j]>cost[p][j])
            {
                lowc[j]=cost[p][j];//p       
                closest[j]=p;
            }
        }
    }
    return ans;
}

あと一歩列挙しますが、ここでは書きません.
kruskal:最小ツリーを複数回求める:まず、kruskalで最小生成ツリーを求め、visit配列で最小生成ツリーのエッジを記録し、合計numバーと仮定した後、最小生成ツリーnum回をループし、毎回最初に求めた最小生成ツリーのエッジ仮定を使わない:最初に最小生成ツリーを求めるには1、2、4の3つのエッジを用い、合計5つのエッジを用い、そのサイクルが3回の場合,それぞれ1,2,4を用いずに最小生成木のMSTを求め,最小のMSTは次小生成木である.
#include
#include
#include
#include
using namespace std;
#define M 99999999
int n, m,w;
int f[10005], sum, cou;
int visit[10005];

struct edge
{
    int u;
    int v;
    int w;
};

edge e[10005];
void init()
{
    int i;
    for (i = 1; i <= n; i++)
    {
        f[i] = i;
    }
}
int cmp(edge a, edge b)
{
    return a.wint getf(int v)
{
    if (f[v] == v)
        return v;
    else
    {
        f[v] = getf(f[v]);
        return f[v];
    }
}

int merg(int v, int u)
{
    int t1, t2;
    t1 = getf(v);
    t2 = getf(u);
    if (t1 != t2)
    {
        f[t2] = t1;
        return 1;
    }
    return 0;
}
int mintree()
{
    int i,flag;
    init();
    flag = 0;
    w = 0;
    cou = 0;
    for (i = 1; i <= m; i++)
    {
        if (merg(e[i].v, e[i].u))
        {
            cou++;
            visit[w++] = i;
        }
        if (cou == n - 1)
        {
            flag = 1;
            break;
        }
    }
    //cout << sum << endl;
    return  flag ;
}
///  
int cimintree()
{
    int j, flag,min;
    min = M;
    for (int i = 0; i < w; i++)
    {
        flag = 0;
        init();
        cou = 0;
        sum = 0;
        for (j = 1; j <= m; j++)
        {
            if (j != visit[i])
            {
                if (merg(e[j].v, e[j].u))
                {
                    cou++;
                    sum = sum + e[j].w;
                }
                if (cou == n - 1)
                {
                    flag = 1;
                    break;
                }
            }
        }
        if (flag&&sum < min) min = sum;
    }
    min = (min == M) ? -1 : min;
    return min;
}
int main()
{
    int i,flag,min;
    while (scanf("%d %d", &n,&m) != EOF)
    {
        if (n == 0)
            break;
        sum = 0;
        cou = 0;
        memset(e, 0, sizeof(e));
        memset(f, 0, sizeof(f));
        for (i = 1; i <= m; i++)
        {
            scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
        }
        sort(e + 1, e + m + 1, cmp);
        flag = mintree();
        if (flag == 0)
        {
            cout << "-1" << endl;
        }
        else
        {
            min = cimintree();
            cout << min << endl;
        }
    }
    return 0;
}