征兵
来源:互联网 发布:不喝牛奶 知乎 编辑:程序博客网 时间:2024/05/01 09:40
题目描述
一个国王,他拥有一个国家。最近他因为国库里钱太多了,闲着蛋疼要征集一只部队要保卫国家。 他选定了 N 个女兵和 M 个男兵,但事实上每征集一个兵他就要花 10000 元 RMB,即使国库里钱再多也伤 不起啊。他发现,某男兵和某女兵之间有某种关系(往正常方面想,一共 R 种关系),这种关系可以使 国王少花一些钱就可以征集到兵,不过国王也知道,在征兵的时候,每一个兵只能使用一种关系来少花 钱。这时国王向你求助,问他最少要花多少的钱才可以招集到 N 个女兵和 M 个男兵。
输入
输入文件的第一行为 T,表示测试数据的组数,对于每组测试数据的格式如下:
第 1 行包括 3 个整数,N,M 和 R;意义如题目描述,
接下来的 R 行 包括 Xi,Yi,Vi 表示如果招了编号为 Xi 的女兵,再招编号为 Yi 的男兵能省 Vi 元 RMB (同样如果招了编号为 Yi 的男兵,再招编号为 Xi 的女兵也能省 Vi 元 RMB)
第 1 行包括 3 个整数,N,M 和 R;意义如题目描述,
接下来的 R 行 包括 Xi,Yi,Vi 表示如果招了编号为 Xi 的女兵,再招编号为 Yi 的男兵能省 Vi 元 RMB (同样如果招了编号为 Yi 的男兵,再招编号为 Xi 的女兵也能省 Vi 元 RMB)
输出
输出文件共 T 行,每行一个整数,即每组数据的最终花费是多少;
样例输入
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%的数据: 1≤T≤1;1≤N,M≤10;1≤R≤10;
对于 40%的数据: 1≤T≤2;1≤N,M≤20;1≤R≤100;
对于 100%的数据:1≤T≤5;1≤N,M≤10,000;1≤R≤50,000;0≤Xi<N;0≤Yi<M;0≤Vi≤10,000;
对于 40%的数据: 1≤T≤2;1≤N,M≤20;1≤R≤100;
对于 100%的数据:1≤T≤5;1≤N,M≤10,000;1≤R≤50,000;0≤Xi<N;0≤Yi<M;0≤Vi≤10,000;
这道题很明显是求一个极值,然后求极值的方法有哪些呢?
无非是DP,贪心,图伦里的生成树,最短路(鬼才会去用数学方法解决这个问题)
首先想想DP,应该是要否定的,毕竟20000个人就摆在那里呢,再乘上一个万级别的肯定是要爆炸的
就算你没有考虑到空间和时间的限制,毅然决然地做了下去,那么恭喜你,你会发现你已经做不下去了。
原因很简单,你发现无法转移了
那么就贪心,怎么个贪法,当然是所有连边中找出几条最大边的来
然后,就莫名其妙地从贪心跳到了生成树
生成树想明白了就简单多了
无非是是吧,后面的M个男兵当成女兵处理(当然,也可以把女兵当男兵处理)
然后,就嘿嘿嘿使用克鲁斯卡尔算法成功过掉
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using
namespace
std;
struct
node
{
int
u,v,cost;
};
node a[100005];
int
f[1000005];
bool
cmp(node i,node j)
{
return
i.cost>j.cost;
}
int
find(
int
X)
{
if
(f[X] != X) f[X]=find(f[X]);
return
f[X];
}
int
main()
{
int
_;
scanf
(
"%d"
,&_);
while
(_--)
{
int
N,M,R;
scanf
(
"%d%d%d"
,&N,&M,&R);
for
(
int
i=0; i<=N+M; i++)
{
f[i]=i;
}
for
(
int
i=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);
int
sum=0;
long
long
ans=0;
for
(
int
i=1; i<=R; i++)
{
int
fx=find(a[i].u);
int
fy=find(a[i].v);
if
(fx != fy)
{
ans+=a[i].cost;
sum++;
f[fx]=fy;
}
if
(sum == N+M-1)
break
;
}
long
long
total=10000*(
long
long
) (N+M);
printf
(
"%lld\n"
,total-ans);
}
}
0 0
- 征兵
- 征兵
- 征兵 conscription
- 征兵问题
- D__恶魔猎手征兵
- 最小生成树kruskal_征兵
- Java征兵系统(可拓展)
- 算法与数据结构第十次作业 征兵
- 109_征兵问题 conscription (poj 3723)
- 征兵制度改,算是革吧!!我的回忆。
- 我的Java之路四:征兵系统
- 4th 【最小生成树&&并查集】征兵
- C++中的回调函数,函数指针理解
- Java发送邮件
- 嵌入式学习--work11 关于SPI的深入学习及软件模拟SPI(LCD调试所遇)
- MySQL触发器
- NOIP考纲 图论
- 征兵
- HDU 1254 推箱子 搜索中搜索
- AdMob(app内嵌广告)原生广告
- 开发android版本的直播app
- 19. Remove Nth Node From End of List (Easy)
- 使用inline-block导致其他元素无法居中
- 第十二周 项目4-l利用遍历思想求解图问题
- 与开发团队高效协作的8个小技巧
- openssl使用实例