征兵

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

读入(conscription.in)

第一行:T,一共T组数据。

接下来T组数据,

第一行包括N,M,R

接下来的R行 包括Xi,Yi,Vi 表示如果招了第Xi个女兵,再招第Yi个男兵能省Vi元(同样表示如果招了第Yi个男兵,再招第Xi个女兵能也省Vi元)

输出(conscription.out)

共T行,表示每组数据的最终花费是多少(因为国库里的钱只有2^31-1,所以保证最终花费在maxlongint范围内)

样例输入

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

数据范围

数据保证T<=5 ,m,n<=10000,r<=50000,Xi<=m,Yi<=n,Vi<=10000,结果<=2^31-1

题目选自http://hzwer.com/3559.html(一大神博客)

这道题是一个最大生成树,因为分成男女两个数组不好处理,我们就可以将女的编号+1,男的编号+N+1,放到一个数组里,这样就会好处理。剩下的就用Kruskal做了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 struct node{
 5  int male,money,female;
 6 };
 7 node array[100005];
 8 int fa[100005];
 9 bool flag[100005];
10 bool cmp(node x,node y)
11 {
12  return x.money>y.money;
13 }
14 int find(int x)
15 {
16  if(x==fa[x])return x;
17  else return fa[x]=find(fa[x]);
18 }
19 int main()
20 {
21     int T; freopen("conscription.in","r",stdin);
22  freopen("conscription.out","w",stdout);
23 scanf("%d",&T);
24 while(T--)
25 {
26  int n,m,r;
27  scanf("%d%d%d",&n,&m,&r);
28  for(int i=1;i<=r;i++)
29  {
30   scanf("%d%d%d",&array[i].female,&array[i].male,&array[i].money);
31   array[i].female++;
32   array[i].male=array[i].male+n+1;
33  }
34  sort(array+1,array+r+1,cmp);
35  for(int i=1;i<=m+n;i++)
36  fa[i]=i;
37  int l=0,ans=0,fe=0,ma=0;
38  for(int i=1;i<=r;i++)
39 {
40  int find1=find(fa[array[i].male]);
41  int find2=find(fa[array[i].female]);
42  if(find1!=find2)
43  {
44   if(!flag[fa[array[i].male]])ma++;
45   if(!fa[array[i].female])fe++;
46  fa[find1]=find2;
47  ans+=array[i].money;
48  flag[fa[array[i].male]]=true;
49  flag[fa[array[i].female]]=true;
50  }
51 }
52 printf("%d\n",10000*(m+n)-ans);
53 }
54 fclose(stdin);
55 fclose(stdout);
56 return 0;
57 }
View Code

 

转载于:https://www.cnblogs.com/Vay-1219-zzssc/p/5863289.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值