征兵

来源:互联网 发布:不喝牛奶 知乎 编辑:程序博客网 时间:2024/05/01 09:40

题目描述

一个国王,他拥有一个国家。最近他因为国库里钱太多了,闲着蛋疼要征集一只部队要保卫国家。 他选定了 个女兵和 个男兵,但事实上每征集一个兵他就要花 10000 元 RMB,即使国库里钱再多也伤 不起啊。他发现,某男兵和某女兵之间有某种关系(往正常方面想,一共 种关系),这种关系可以使 国王少花一些钱就可以征集到兵,不过国王也知道,在征兵的时候,每一个兵只能使用一种关系来少花 钱。这时国王向你求助,问他最少要花多少的钱才可以招集到 个女兵和 个男兵。 

输入

输入文件的第一行为 T,表示测试数据的组数,对于每组测试数据的格式如下:
第 
行包括 个整数,N和 R;意义如题目描述,
接下来的 
行 包括 XiYiVi 表示如果招了编号为 Xi 的女兵,再招编号为 Yi 的男兵能省 Vi 元 RMB (同样如果招了编号为 Yi 的男兵,再招编号为 Xi 的女兵也能省 Vi 元 RMB)

输出

输出文件共 行,每行一个整数,即每组数据的最终花费是多少;

样例输入

2
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781
5 5 10
2 4 9820
3 2 6236
3 1 8864
2 4 8326
2 0 5156
2 0 1463
4 1 2439
0 4 4373
3 4 8889
2 4 3133

样例输出

71071
54223

提示


【数据规模】

对于 20%的数据: 1T1;1N,M10;1R10;

对于 
40%的数据: 1T2;1N,M20;1R100;

对于 
100%的数据:1T5;1N,M10,000;1R50,000;0Xi<N;0Yi<M;0Vi10,000;


这道题很明显是求一个极值,然后求极值的方法有哪些呢?

无非是DP,贪心,图伦里的生成树,最短路(鬼才会去用数学方法解决这个问题)

首先想想DP,应该是要否定的,毕竟20000个人就摆在那里呢,再乘上一个万级别的肯定是要爆炸的

就算你没有考虑到空间和时间的限制,毅然决然地做了下去,那么恭喜你,你会发现你已经做不下去了。

原因很简单,你发现无法转移了

那么就贪心,怎么个贪法,当然是所有连边中找出几条最大边的来

然后,就莫名其妙地从贪心跳到了生成树

生成树想明白了就简单多了

无非是是吧,后面的M个男兵当成女兵处理(当然,也可以把女兵当男兵处理)

然后,就嘿嘿嘿使用克鲁斯卡尔算法成功过掉

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
 
usingnamespace std;
 
structnode
{
    intu,v,cost;
};
 
node a[100005];
intf[1000005];
 
boolcmp(node i,node j)
{
    returni.cost>j.cost;
}
 
intfind(intX)
{
    if(f[X] != X) f[X]=find(f[X]);
    returnf[X];
}
 
intmain()
{
    int_;
    scanf("%d",&_);
    while(_--)
    {
        intN,M,R;
        scanf("%d%d%d",&N,&M,&R);
        for(inti=0; i<=N+M; i++)
        {
            f[i]=i;
        }
        for(inti=1; i<=R; i++)
        {
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].cost);
            a[i].v+=N;
        }
        sort(a+1,a+R+1,cmp);
        intsum=0;
        longlong ans=0;
        for(inti=1; i<=R; i++)
        {
            intfx=find(a[i].u);
            intfy=find(a[i].v);
            if(fx != fy)
            {
                ans+=a[i].cost;
                sum++;
                f[fx]=fy;
            }
            if(sum == N+M-1) break;
        }
        longlong total=10000*(longlong) (N+M);
        printf("%lld\n",total-ans);
    }
}

0 0
原创粉丝点击