POJ 2377 Bad Cowtractors (prime+堆优化)

13 篇文章 0 订阅
2 篇文章 0 订阅

题目链接:(—_—) zZ


题目大意:有n个点, m条边,每条边有一定的花费, n个点是连通的(没有循环)且花费最大


思路:用最小生成树算法就ok了, priem时要判重边


code:prime+堆优化(第一回用,wa了半天生气

#include <stdio.h>
#include <string.h>
struct
{
    int weight, num;
}dis[1002];
int n = 0, m = 0, ans = 0, total = 0, flag = 0, head[1002], map[1002][1002];
void swap(int a, int b)
{
    dis[0] = dis[a];
    dis[a] = dis[b];
    dis[b] = dis[0];
    head[dis[a].num] = a;
    head[dis[b].num] = b;
}
void sift(int l)
{
    int i = 0, j = 0, x = 0;
    x = dis[l].weight;
    i = l; j = 2*i;
    while(j<=total)
    {
        if(j<total && dis[j].weight<dis[j+1].weight) j++;
        if(x<dis[j].weight)
        {
            swap(i, j);
            i = j;
            j = 2*i;
        }
        else
            break;
    }
    dis[i].weight = x;
}
void heap_sort()
{
    int i = 0;
    for(i = n/2; i>0; i--)
        sift(i);
}
void prime()
{
    int i = 0, u = 0, p = 0;
    for(i = 2; i<=n; i++)
    {
        dis[++total].weight = map[1][i];
        head[i] = total;//记录顶点i在dis中的位置
        dis[total].num = i;//记录当前为顶点i
    }
    head[1] = total;
    while(total)
    {
        heap_sort();
        u = dis[1].num;
        ans += dis[1].weight;
        if(dis[1].weight == -1)//判断连通不
            flag = 1;
        swap(1, total);
        total--;
        for(i = 2; i<=n; i++)
        {
            p = head[i];//通过当前点更新其他点
            if(p<=total && dis[p].weight<map[u][i])
                dis[p].weight = map[u][i];
        }
    }
}
int main()
{
    int i = 0, u = 0, v = 0, cost = 0, count = 0;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        memset(map, -1, sizeof(map));
        for(i = 0; i<m; i++)
        {
            scanf("%d %d %d", &u, &v, &cost);
            if(map[u][v] == -1 || map[u][v]<cost)
                map[u][v] = map[v][u] = cost;
        }
        ans = flag = 0;
        prime();
        if(!flag)
            printf("%d\n", ans);
        else
            printf("-1\n");
    }
    return 0;
}



code: prime

#include <stdio.h>
#include <string.h>
int n = 0, m = 0, map[1002][1002], used[1002], dis[1002];
void prime()
{
    int i = 0, j = 0, k = 0, min = 0;
    memset(used, 0, sizeof(used));
    for(i = 1; i<=n; i++)
        dis[i] = map[1][i];
    used[1] = 1;
    for(i = 1; i<=n; i++)
    {
        min = 0;
        for(j = 1; j<=n; j++)
            if(!used[j] && min<dis[j])
            {
                min = dis[j];
                k = j;
            }
        used[k] = 1;
        for(j = 1; j<=n; j++)
        {
            if(!used[j] && map[k][j] != -1 && dis[j]<map[k][j])
                dis[j] = map[k][j];
        }
    }
}
int main()
{
    int i = 0, j = 0, u = 0, v = 0, cost = 0, ans = 0, count = 0;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        memset(map, -1, sizeof(map));
        for(i = 0; i<m; i++)
        {
            scanf("%d %d %d", &u, &v, &cost);
            if(map[u][v] == -1 || map[u][v]<cost)
                map[u][v] = map[v][u] = cost;
        }
        prime();
        for(i = 1; i<=n; i++)
            if(used[i])
                count++;
        if(count == n)
        {
            for(i = 2; i<=n; i++)
                ans += dis[i];
            printf("%d\n", ans);
        }
        else
            printf("-1\n");
    }
    return 0;
}

code:kruskal

#include <stdio.h>
#include <stdlib.h>
struct node
{
    int u, v, cost;
} edge[20002];
int n = 0, m = 0, count = 0, sum = 0, father[1002], rank[1002];
int cmp(void const *a, void const *b)
{
    return -((*(struct node *)a).cost-(*(struct node *)b).cost);
}
int find(int x)
{
    if(father[x] != x)
        father[x] = find(father[x]);
    return father[x];
}
void Union(int x, int y)
{
    if(rank[x]>rank[y])
        father[y] = x;
    else
    {
        if(rank[x] == rank[y])
            rank[y]++;
        father[x] = y;
    }
}
void kruskal()
{
    int i = 0, fx = 0, fy = 0;
    sum = 0;
    for(i = 0; i<m; i++)
    {
        fx = find(edge[i].u); fy = find(edge[i].v);
        if(fx != fy)
        {
            Union(fx, fy);
            sum += edge[i].cost;
            count++;
        }
    }
}
int main()
{
    int i = 0;
    while(scanf("%d %d", &n, &m) != EOF)
    {
        for(i = 1; i<=n; i++)
        {
            rank[i] = 0;
            father[i] = i;
        }
        for(i = 0; i<m; i++)
            scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].cost);
        qsort(edge, m, sizeof(edge[0]), cmp);
        kruskal();
        if(count == n-1)
            printf("%d\n", sum);
        else
            printf("-1\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值