Conscription
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 14661   Accepted: 5102

Description

Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be his soldiers. To collect a soldier without any privilege, he must pay 10000 RMB. There are some relationships between girls and boys and Windy can use these relationships to reduce his cost. If girl x and boy y have a relationship d and one of them has been collected, Windy can collect the other one with 10000-d RMB. Now given all the relationships between girls and boys, your assignment is to find the least amount of money Windy has to pay. Notice that only one relationship can be used when collecting one soldier.

Input

The first line of input is the number of test case.
The first line of each test case contains three integers, NM and R.
Then R lines followed, each contains three integers xiyi and di.
There is a blank line before each test case.

1 ≤ NM ≤ 10000
0 ≤ R ≤ 50,000
0 ≤ xi < N
0 ≤ yi < M
0 < di < 10000

Output

For each test case output the answer in a single line.

Sample Input

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

Sample Output

71071
54223


题意:有N+M个顶点,边:两个顶点之间的亲密度。
    单独获取某个顶点的花费是10000;
    如果两个顶点的亲密度为x,我已经获取了其中一个顶点,那么获取另一个顶点花费10000-x。   
现在你要把所有的顶点全部获取,算出最小花费。


【方法1】
我们可以想到这是一个森林,我们需要求最小生成树(最小花费)。
由于权值x越大花费越小,所以我们把权值取反为-x,求出最小生成树(通过关系获取比直接获取可以少花费多少),
然后再加上每个点花费的10000,就得到了我们的总花费。


【方法2】
你可能会说,直接把权值设置为10000-x也可以写,
但是考虑到我们求出最小生成树之后还要再求出连通分量,
总花费 = 最小生成树(通过关系获取)+ 连通分量*10000。 明显比前一种算法复杂度要高(主要是我还不会写连通分量)。 不过不会写不要紧,我们可以用Kruskal算法用到的并查集,
并查集中的parent数组保存的就是属于哪棵树,
所以算一下parent中有几个不同的值就可以得到连通分量。

Kruskal算法讲解:http://www.cnblogs.com/zhangjiuding/p/7796526.html

代码:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
#define MAX_N 20010
#define MAX_E 50010
#define INF 2147483647 struct edge {
int u,v,cost;
}; bool cmp(const edge & e1,const edge &e2){
return e1.cost < e2.cost;
} edge es[MAX_E]; //边集
int V,E; //顶点数和边数 int par[MAX_N]; //par[i]表示i节点的父节点
int rank[MAX_N]; // 树的高度 //初始化n个元素
void init(int n){
for(int i = ;i < n; i++){
par[i] = i;
rank[i] = ;
}
} //查询包含x节点的树的根
int find(int x){
if(par[x] == x) return x;
else return par[x] = find(par[x]);
} //合并 x和y所属的集合
void unite(int x,int y){
x = find(x);
y = find(y);
if(x == y) return; if(rank[x] < rank[y]){
par[x] = y;
}else{
par[y] = x;
if(rank[x] == rank[y]) rank[x]++;
}
} //判断x和y是否属于同一个集合
bool same(int x,int y){
return find(x) == find(y);
} int kruskal(){
sort(es, es + E, cmp);
init(V);
int res = ;
for(int i = ;i < E; i++ ){
edge e = es[i];
if(!same(e.u,e.v)){
unite(e.u, e.v);
res += e.cost;
}
}
return res;
} int main(){
int t;
cin >> t;
while(t--){ int n,m,r;
cin >> n >> m >> r;
V = n+m;
E = r;
for(int i = ;i < r; i++){
edge e;
scanf("%d%d%d",&e.u,&e.v,&e.cost);
e.cost = - e.cost;
e.v += n;
es[i] = e;
} cout << V* + kruskal() << endl;
}
return ;
}

 

POJ 3723 Conscription (Kruskal并查集求最小生成树)的更多相关文章

  1. POJ 3723 Conscription(并查集建模)

    [题目链接] http://poj.org/problem?id=3723 [题目大意] 招募名单上有n个男生和m个女生,招募价格均为10000, 但是某些男女之间存在好感,则招募的时候, 可以降低与 ...

  2. POJ 1611 The Suspects (并查集求数量)

    Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, wa ...

  3. Minimum Spanning Tree.prim/kruskal(并查集)

    开始了最小生成树,以简单应用为例hoj1323,1232(求连通分支数,直接并查集即可) prim(n*n) 一般用于稠密图,而Kruskal(m*log(m))用于系稀疏图 #include< ...

  4. Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 并查集求奇偶元环

    D. Dividing Kingdom II   Long time ago, there was a great kingdom and it was being ruled by The Grea ...

  5. C. Edgy Trees Codeforces Round #548 (Div. 2) 并查集求连通块

    C. Edgy Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  6. HDU 3018 Ant Trip (并查集求连通块数+欧拉回路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 题目大意:有n个点,m条边,人们希望走完所有的路,且每条道路只能走一遍.至少要将人们分成几组. ...

  7. TOJ 2815 Connect them (kruskal+并查集)

    描述 You have n computers numbered from 1 to n and you want to connect them to make a small local area ...

  8. Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)

    题意:给出n个点的坐标,要把n个点连通,使得总距离最小,可是有m对点已经连接,输入m,和m组a和b,表示a和b两点已经连接. 思路:两种做法.(1)用prim算法时,输入a,b.令mp[a][b]=0 ...

  9. POJ-2421Constructing Roads,又是最小生成树,和第八届河南省赛的引水工程惊人的相似,并查集与最小生成树的灵活与能用,水过~~~

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K               Description There are N v ...

随机推荐

  1. vue 父子组件通信props/emit

    props 1.父组件传递数据给子组件 父组件: <parent> <child :childMsg="msg"></child>//这里必须要 ...

  2. 实现简单的List功能

    简单的实现javaArrayList(可扩容)功能,实现新增,删除,取数据. package algorithm.data_structure; /** * 模拟ArrayList类的功能 * @au ...

  3. mysql case when then 使用

    建表:create table hank (id int,name varchar(20)); 插入数据:insert into hank values(1,'A');insert into hank ...

  4. (转)硬盘结构,主引导记录MBR,硬盘分区表DPT,主分区、扩展分区和逻辑分区,电脑启动过程

    硬盘结构硬盘有很多盘片组成,每个盘片的每个面都有一个读写磁头.如果有N个盘片.就有2N个面,对应2N个磁头(Heads),从0.1.2开始编号.每个盘片的半径均为固定值R的同心圆再逻辑上形成了一个以电 ...

  5. 腾讯测试工程师:你以为会打LOL就能做测试了?

    周日参加完公司团建,回家路上拼到一个IT界的老司机,他和几个朋友组件团队承接开发项目,知道我是做测试的,问了我一个问题: “你们大公司的测试都做什么?” “测试应该不好模仿吧?” 刚开始我也不清楚他的 ...

  6. ZBrush中Blob点滴笔刷介绍

    对于ZBrush®来说,笔刷的使用时至关重要的,ZBrush中给我们提供了越来越多的笔刷的同时,我们也要根据经验来合理选择笔刷.本文内容小编将分享Blob点滴笔刷的简单介绍,该笔刷在使用时笔头犹如一股 ...

  7. TF基础2

    1.常用API 1.图,操作和张量 tf.Graph,tf.Operation,tf.Tensor 2.可视化 TensorBoard 3.变量作用域 在TF中有两个作用域(scope),一个是nam ...

  8. Kattis - CD

    CD Jack and Jill have decided to sell some of their Compact Discs, while they still have some value. ...

  9. day01 编程概述及计算机组成原理

    目录 编程概述 计算机硬件的五大组成部分 Central Processing Unit(cpu中央处理器) 存储器 输入,输出设备 打开QQ的流程 计算机五大组成部分补充 多核CPU ×64/x86 ...

  10. layui动态修改select的选中项

    layui动态修改select的选中项:(在layUI下给select设置默认选项) 例: $("select[name='result']").val(11); //重新渲染表单 ...