PKU 1679 The Unique MST

判断最小生成树是否唯一,可以证明如果MST不唯一,必然是由于有两条边的权相等(反过来不成立),那么在第一次求MST时可以标记这类边,然后逐一去掉重新求MST,看是否和之前的相等。

/*

    判断最小生成树是否唯一, kruskal 

*/

# include <stdio.h>

# include <stdlib.h>



# define N 105

# define M 5005



int n, m;

int p[N];

int r[M], u[M], v[M], w[M];

char h[M], ud[M], pi[M];



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

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

{

    int xx = *(int *)x, yy = *(int *)y;

    return w[xx] - w[yy];

}



int kruskal(char bj)

{

    int i, ret = 0, e, x, y;

    

    for (i = 1; i <= n; ++i) p[i] = i;

    for (i = 1; i <= m; ++i) if (h[e = r[i]])

    {

        x = find(u[e]), y = find(v[e]);

        if (x != y)

        {

            p[x] = y;

            ret += w[e];

            if (!bj && pi[e]) ud[e] = 1;

        }

    }

    

    return ret;

}



void solve(void)

{

    int i, ans;

    

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

    {

        pi[i] = ud[i] = 0;

        r[i] = i, h[i] = 1;

    }    

    qsort(r+1, m, sizeof(r[0]), cmp);

    for (i = 2; i <= m; ++i) if (w[r[i]] == w[r[i-1]])

        pi[r[i]] = pi[r[i-1]] = 1;

    

    ans = kruskal(0);

    for (i = 1; i <= m; ++i) if (ud[i])

    {

        h[i] = 0;

        if (ans == kruskal(1))

        {

            puts("Not Unique!");

            return ;

        }

        h[i] = 1;

    }

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

}



void init(void)

{

    int i;

    

    scanf("%d%d", &n, &m);

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

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

}



int main()

{    

    int T;

    

    scanf("%d", &T);

    while (T--)

    {

        init();

        solve();

    }

    

    return 0;

}

COJ 的题目排列怎么乱了,以前的题很多都找不到了,包括有一道(幻想乡的路?)也是要判断MST是否唯一。

你可能感兴趣的:(unique)