poj1679 The Unique MST

这题只是简单的最小生成树的一个变形。 可以用kruskal 先进行求最小生成树, 然后, 用dp 记录每一个点之间的最大长度。 然后枚举每一条边(未在最小生成树中的), 如果发现有和最小生成树中的边的最大相等的就返回不唯一, 否则如果都大的话, 返回唯一

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 102
using namespace std;

struct node
{
    int left, right, val;
}map[maxn* maxn], edge[maxn * maxn];

int e[maxn][maxn];
int map_count;
int parent[maxn];
int n, m, sum;
int edge_min[maxn][maxn];
int fleft, fright, fval;

void add(int left, int right)
{
    edge_min[left][0] ++;
    edge_min[left][edge_min[left][0]] = right;
    edge_min[right][0] ++;
    edge_min[right][edge_min[right][0]] = left;
}

void del(int left, int right)
{
    int k = 1;
    while (edge_min[left][k] != right)k ++;
    while (k < edge_min[left][0]) edge_min[left][k] = edge_min[left][k + 1], k ++;
    k = 1;
    while (edge_min[right][k] != left) k ++;
    while (k < edge_min[right][0]) edge_min[right][k] = edge_min[right][k + 1], k ++;
    edge_min[left][0]--;
    edge_min[right][0] --;
}

int find(int x)
{
    if (x != parent[x]) x = find(parent[x]);
    return parent[x];
}

int point_find;
void find_max(int parent, int current, int left , int right, int val)
{
    if (point_find == current)
    {
        fleft = left;
        fright = right;
        fval  = val;
        return;
    }
    for (int i = 1; i <= edge_min[current][0]; i ++)
    {
        if (parent != edge_min[current][i])
        {
            if (e[current][edge_min[current][i]] > val)
            {
                find_max(current, edge_min[current][i], current, edge_min[current][i], e[current][edge_min[current][i]]);
            }
            else
            {
                find_max(current, edge_min[current][i], left, right, val);
            }
        }
    }
    return;
}

int cmp(const node &a , const node &b)
{
    if (a.val <= b.val)
    {
        return true;
    }
    return false;
}

void init()
{
    int i, x, y, val;
    for (i = 1; i <= n; i ++)
    {
        parent[i]  = i;
    }
    for (i = 0; i < m; i ++)
    {
        scanf("%d%d%d", &edge[i].left, &edge[i].right, &edge[i].val);
        e[edge[i].left][edge[i].right] = e[edge[i].right][edge[i].left] = edge[i].val;
    }
    map_count = 0;
    sort(edge, edge + m, cmp);
    memset(edge_min, 0, sizeof(edge_min));
}

void krus()
{
    int i = 0, cou = 0;
    sum = 0;
    int left, right, left_parent, right_parent, val;

    for (i = 0; i < m; i ++)
    {
        left = edge[i].left;
        right = edge[i].right;
        left_parent = find(left);
        right_parent = find(right);

        if (left_parent != right_parent)
        {
            parent[left_parent] = parent[right_parent];
            add(left, right);
            sum += edge[i].val;
            cou++;
        }
        else
        {
            find_max(left, right, 0, 0, 0);
            if (fval > edge[i].val)
            {
                sum = sum + edge[i].val - fval;
                del(fleft, fright);
                map_count ++;
                map[map_count].left = fleft;
                map[map_count].right = fright;
                map[map_count].val = fval;
                add(edge[i].left, edge[i].right);
            }
            else
            {
                map_count ++;
                map[map_count] = edge[i];
            }
        }
        if (cou == n - 1)
        {
            break;
        }
    }
    i ++;
    while ( i < m)
    {
        map_count ++;
        map[map_count] = edge[i ++];
    }
    
    return;
}

int max_left[maxn][maxn], max_right[maxn][maxn];
int max_val[maxn][maxn];

void dfs(int parent, int current, int left, int right, int val)
{
    int x;
    for (int i = 1; i <= edge_min[current][0]; i ++)
    {
        x = edge_min[current][i];
        if (x != parent)
        {
            if (e[current][x] > val)
            {
                max_left[point_find][x] = current;
                max_right[point_find][x] = x;
                max_val[point_find][x] = e[current][x];
                dfs(current, x, current, x, e[current][x]);
            }
            else
            {
                max_left[point_find][x] =left;
                max_right[point_find][x] = right;
                max_val[point_find][x] = val;
                dfs(current, x, left, right, val);
            }
        }
    }
}

bool judge()
{
    for (int i = 1; i <= n ; i ++)
    {
        point_find = i;
        dfs(i, i, 0, 0, 0);
    }

    for (int i = 1; i <= map_count; i ++)
    {
        
        if (max_val[map[i].left][map[i].right] == map[i].val)
        {
            return false;
        }
    }
    return true;
}

int main()
{
    int count_int;
    scanf("%d", &count_int);
    while (count_int --)
    {
        scanf("%d%d", &n, &m);
        init();
        krus();
        if (judge())
        {
            printf("%d\n", sum);
        }
        else
        {
            printf("Not Unique!\n");
        }
    }
    return 0;
}
posted @ 2012-04-10 13:20  CY_K_YC  阅读(117)  评论(0编辑  收藏  举报