POJ 3723 MST(建军队的最小花费)

来源:互联网 发布:js图片上传插件 编辑:程序博客网 时间:2024/06/05 10:26

题意:
      一个人想要组建一个军队,他需要雇佣n个女生,m个男生,每个人花费10000,然后

给你r组朋友关系,每组关系都有一个权值d,表示如果你买了这组关系中的一个人之后再去

买另一个可以少花d元,最后问你达到目的的最小化费。

思路:
      跑一遍最大生成树,然后(n+m)*10000-mst ,我们来分析下:
对于每个人只能被购买一次,对于已经购买好了的两个人之间的优惠已经没用了,<对应的

是树上任意两个点之间的路径只有一条,就是连接方式只有一种>,那么也就是说我们可以

贪心的去想,先找优惠做多的,人后在找优惠第二多的,如果当前两个点都已经优惠过了就

continue,那么不正好就是在“克鲁斯卡尔”吗?只不过求的是最大生成树,如果用的是“

普里姆”的话,注意一点就是树可能不只一颗,就是图可能不连通。

 

 

#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

typedef struct
{
    int a ,b ,c;
}EDGE;

bool camp(EDGE a ,EDGE b)
{
    return a.c > b.c;
}

EDGE edge[55000];
int mer[22000];

int finds(int x)
{
    return x == mer[x] ? x : mer[x] = finds(mer[x]);
}

int main ()
{
    int n ,m ,k ,i ,t;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d %d %d" ,&n ,&m ,&k);
        for(i = 1 ;i <= k ;i ++)
        {
           scanf("%d %d %d" ,&edge[i].a ,&edge[i].b ,&edge[i].c);
           edge[i].a ++ ,edge[i].b += (1 + n);
        }
        for(i = 1 ;i <= n + m ;i ++)
        mer[i] = i;
        int sum = 0;
        sort(edge + 1 ,edge + k + 1 ,camp);
        for(i = 1 ;i <= k ;i ++)
        {
            int xx = finds(edge[i].a);
            int yy = finds(edge[i].b);
            if(xx != yy)
            {
               sum += edge[i].c;
               mer[xx] = yy;
            }
        }
        printf("%d\n" ,(n + m) * 10000 - sum);
    }
    return 0;
}

0 0
原创粉丝点击