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, N, M and R.
Then R lines followed, each contains three integers xi, yi and di.
There is a blank line before each test case.

1 ≤ N, M ≤ 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. Ubuntu16.04系统安装搜狗输入法

    前言:正常双击.deb软件包安装搜狗输入法会有bug,需要按照下面操作进行消除错误. 一.下载搜狗输入法Linux版软件包 下载地址为:http://pinyin.sogou.com/linux/ , ...

  2. BZOJ 1818 线段树+扫描线

    思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...

  3. c#设计模式(1)

    本文摘取自吕震宇的博客园文章,版权归吕震宇仅供个人学习参考.转载请标明原作者吕震宇. 这学期开设设计模式课程,将课件放上来. 课本:<C#设计模式>,电子工业出版社,ISBN 7-5053 ...

  4. HDU 2037 今年暑假不AC【贪心】

    解题思路:即为给出一个总长度确定的区间,再输入不同的子区间,求在这个总区间里面包含的不相交的子区间最多有多少个. 可以由最特殊的情况来想,即给出的这些子区间现在都不相交,比如 ----- (1,3)  ...

  5. jquery获取自定义属性的值

    //获取属性值 1 <div id="text" value="黑哒哒的盟友"><div> jQuery取值: $("#tex ...

  6. Eclipse中重置(还原)GIT分支

    重置(还原)GIT分支: 1.  右击项目——Team——Reset…: 2.  在弹出的Reset框中选择要重置(还原)的分支——Reset,即可完成.

  7. 使用面向对象技术创建高级 Web 应用程序

    作者: 出处: 使用面向对象技术创建高级 Web 应用程序 来源:开源中国社区 作者:oschina 最近,我面试了一位具有5年Web应用开发经验的软件开发人员.她有4年半的JavaScript编程经 ...

  8. css font-family 字体组

    介绍图片来自: http://www.runoob.com/cssref/css-websafe-fonts.html

  9. java对word文档的操作(提取标题和内容等)-直接操作或poi工具包或freemarker+xml或html转word

    1,java自带工具包实现对word的排版和写入 import java.awt.Color; import java.io.FileNotFoundException; import java.io ...

  10. PHP实现的毫秒定时器,同时解决进程不重复堆积

    定时器任务,在WEB应用比较常见,如何使用PHP实现定时器任务,大致有两种方案:1)使用Crontab命令,写一个shell脚本,在脚本中调用PHP文件,然后定期执行该脚本:2)配合使用ignore_ ...