COJ 1106 幻想乡的路

题意:若第二小生成树代价与最小生成树代价相等输出Not Unique!,否则输出最小代价;

对最小生成树的每一边标记后重新计算不含这条边的最小生成树,若代价与 MST 的相等说明有多种方案,复杂度为O(N^3)。

# include <stdio.h>

# include <string.h>



# define N 20005



typedef struct

{

    int u, v, w;

} Road;



char f[N], use[N];

int n, m, p[205];

Road r[N];



int cmp(const void *x, const void *y)

{

    return (*(Road*)x).w>(*(Road*)y).w ? 1:-1;

}

int find(int x)

{

    return x==p[x] ? x:(p[x] = find(p[x]));

}



int main()

{

    int i, ans, ok;



    while (~scanf("%d%d", &n, &m))

    {

        for (i = 1; i <= m; ++i)

            scanf("%d%d%d",&r[i].u, &r[i].v, &r[i].w);



        qsort(r+1, m, sizeof(Road), cmp);



        memset(f, 0, sizeof(f));

        memset(use, 0, sizeof(use));



        ok = 0;

        ans = kruskal(1);

        if (ans > 0)

        {

            for (i = 1; i <= m; ++i)

                if (use[i])

                {

                    f[i] = 1;

                    if (ans == kruskal(0))

                    {

                        ok = 1;

                        break;

                    }

                    f[i] = 0;

                }

        }

        else ok = 1;



        if (ok) puts("Not Unique!");

        else printf("%d\n", ans);

    }



    return 0;

}



int kruskal(int min)

{

    int i, ans, x, y, cnt;



    for (i = 1; i <= n; ++i)

        p[i] = i;



    cnt = ans = 0;

    for (i = 1; i <= m; ++i)

        if (!f[i])

        {

            x = find(r[i].u);

            y = find(r[i].v);

            if (x != y)

            {

                p[x] = y;

                ans += r[i].w;

                ++cnt;

                if (min) use[i] = 1;  /* 调试了很久,就是这句话写在了外面 */

            }

        }



    return cnt==n-1 ? ans:-1;

}

你可能感兴趣的:(OJ)