陕西省第一届ACM程序设计竞赛D题(最大生成树)

Problem 1268 - Donald’s company
Time Limit: 1000MS      Memory Limit: 65536KB      Difficulty:    
Total Submit: 3     Accepted: 3     Special Judge: No 
Description

Donald established a company. This company needs to employ M boys and N girls. The fee for employing one person is K RMB, but Donald finds that there exists a certain complex relationship between some boys and girls. The fee for employing can be decreased if this relationship can be fully made use of. Given the intensity of relationship between the ith boy and the jth girl is Rij, it needs the company K RMB to hire the ith boy or the jth girl first, and then it only needs (K- Rij) RMB to hire the jth girl or the ith boy.

All the X kinds of relationship between boys and girls are given and a person can be hired at most through one type of the relationship. Now, please help Donald to calculate the minimum expense he needs to spend to hire all the M boys and N girls.

Input
  The input consists of several test cases.
  The first line of the input contains a single integer T (0 < T ≤ 100), the number of test cases.
  Each case contains several lines.
   The first line of each case contains four integers M, N, K, X (0 < M,N ≤ 10000, 0 < K ≤ 10000, 0 ≤ X ≤ 50000), which meaning are described above.
   Then followed by X lines, each of which contains three integers i, j, Rij (0 ≤ i < M, 0 ≤ i <N, 0 < Rij ≤ K), which indicates the intensity of relationship between the ith boy and the jth girl is Rij.
Output
  For each test case, output the least expense of hiring all the M boys and N girls.
Sample Input
3
2 2 50 2
0 1 10
1 0 20
2 2 100 4
0 0 10
0 1 20
1 0 30
1 1 40
4 3 10 6
0 2 2
1 2 4
3 1 5
2 0 1
1 1 3
3 2 2
Sample Output
170
310
55

首先我们需要把题目抽象成图论模型,把有关系的都连上一条边,因为只能对应一种关系,所以它不会存在环,是一颗树,这个从样例数据也也能分析道,最后的答案是K*所有人-RR表示这颗树的边权,所以这是一道最大生成树问题。复杂度就是生成树的复杂度O(Mlog(M))


/*************************************************************************
* author:crazy_石头
* algorithm:MST
* date:2013/09/29
**************************************************************************/
#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

#define MAX 50000
 

struct data
{
    int a,b,val;
}x[MAX];
 

struct USFtree
{
    int p,rank;
}note[MAX*2];
 

void makeset(int m)     //点的初始化
{
    note[m].p=m;
    note[m].rank=0;
}

int find(int m)      //并查集,查找祖先节点
{
    while(m!=note[m].p)
        m=note[m].p;
    return m;
}

void union2(int m,int n)    //并查集,两颗子树按秩合并;也可以路径压缩的;
{
    m=find(m);
    n=find(n);
    if(n==m)
        return;
    else
    {
        if(note[n].rank>note[m].rank)
            note[m].p=n;
        else
        {
            note[n].p=m;
            if(note[n].rank==note[m].rank)
                note[m].rank++;
        }
    }
}

bool cmp(const data &a, const data &b)
{
    return a.val>b.val;
}

int main()
{
    int n,m,i,t,cas,k,r,cnt;
    scanf("%d",&cas);
    while(cas--)
    {
        memset(note,0,sizeof(note));
        cnt=0;
        scanf("%d%d%d%d",&n,&m,&k,&r);
        for(i=0;i<r;i++)
        {
            scanf("%d%d%d",&x[i].a,&t,&x[i].val);
            x[i].b=t+n;   //女生的标号
        }
        sort(x,x+r,cmp);    //边权从大到小排序
        for(i=0;i<n+m;i++)
            makeset(i);
        for(i=0;i<r;i++)    //最大生成树算法
        if(find(x[i].a)!=find(x[i].b))
        {
            cnt+=x[i].val;
            union2(x[i].a,x[i].b);
        }
        printf("%d\n",k*(m+n)-cnt);   //输出答案
    }
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM程序设计竞赛基础教程(第2版)》是一本经典的程序设计竞赛教材,旨在帮助学习者掌握ACM程序设计竞赛的基础知识和解技巧。 该教材以清晰简明的语言详细介绍了ACM竞赛所需的基本知识,包括数据结构、算法设计与分析、动态规划、图论等。同时,它提供了大量的例和习,帮助学习者巩固知识,培养解能力。 与其他类似的教材相比,这本教材具有以下几个特点: 首先,该教材内容全面,不仅介绍了ACM竞赛中常见的基础知识,还涵盖了一些高级内容。通过学习这本教材,学习者能够建立起扎实的程序设计基础,为进一步深入学习和应用打下坚实的基础。 其次,该教材注重实战,提供了大量的例和习。这些目都是经过精心挑选和设计的,能够帮助学习者理解和掌握各种解技巧。通过反复练习,学习者能够逐渐提高自己的编程水平和解能力。 最后,该教材配有详细的讲解和解答,帮助学习者更好地理解和掌握知识点。无论是初学者还是有一定基础的学习者,都可以根据自己的情况选择性地学习和提升。 《ACM程序设计竞赛基础教程(第2版)》是一本值得推荐的优秀教材,它不仅适用于参加ACM竞赛的学生,也适用于对算法和程序设计感兴趣的人。通过学习这本教材,学习者能够提高自己的编程能力,锻炼解决问的思维方式,为将来的学习和工作打下良好的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值