Description

In graph theory, a pseudoforest is an undirected graph in which every connected component has at most one cycle. The maximal pseudoforests of G are the pseudoforest subgraphs of G that are not contained within any larger pseudoforest of G. A pesudoforest is larger than another if and only if the total value of the edges is greater than another one’s.

 

Input

The input consists of multiple test cases. The first line of each test case contains two integers, n(0 < n <= 10000), m(0 <= m <= 100000), which are the number of the vertexes and the number of the edges. The next m lines, each line consists of three integers, u, v, c, which means there is an edge with value c (0 < c <= 10000) between u and v. You can assume that there are no loop and no multiple edges. 
The last test case is followed by a line containing two zeros, which means the end of the input. 
 

Output

Output the sum of the value of the edges of the maximum pesudoforest. 
 

Sample Input

3 3
0 1 1
1 2 1
2 0 1
4 5
0 1 1
1 2 1
2 3 1
3 0 1
0 2 2
0 0
 

Sample Output

3
5
 
说说题目意思是必要的,毕竟小笼包都给我解释了好久,真是难以让人理解,题目意思就是合并出一个假森林出来,这个森林的环只能有一个,所谓环就是比如当0, 1, 2建立集合关系的时候
这个时候2已经链接到0了,也就是说0是可以到2的,这个时候如果系统在给你一组数据类似于2, 0的时候,继续合并,则0到1到2再到0,把它想成一圈,是不是就是一个环了,好了,理解这里应该就没有什么难度了,接下来的主要问题就是合并时的判断了,当两个节点同属于一个集合的时候,看看这个集合已经形成环了没有,如果形成了,就不能加入了,反之则可以,还有一种情况就是
两个节点分别属于不同的集合,因为合并的时候要考虑环的数量,所以当两个集合合并后新集合的环数量超过1也是不行的,还有一些问题我会在注释中注明:
 
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std; const int MX = 111111;
int road[MX];
int sign[MX];
int rec[MX];
int n, m; struct Node {
int a, b, c;
}node[MX]; bool comp(const Node& n1, const Node& n2) {
return n1.c > n2.c;//对价值进行排序,优先考虑放大的,贪心啦
} void ini() {
for (int i = 0; i < n; i++) {
road[i] = i;
sign[i] = 0;//注意这个是用来标记环的数量的
rec[i] = 1;//注意这个是用来标记集合中的元素个数的,因为我采用了新的合并方法,就是把小集合合并到大集合,当然你也不用在意这种细节啦,你可以继续使用自己的合并方式
}
} int FindRoot(int r) {//在使用路径压缩查找跟节点的时候我没有使用递归了,主要是不好进行各种标记
int root = r;
while (road[root] != root) root = road[root]; int t1 = r;
int t2 = r;
while (road[t1] != root) {
t2 = road[t1];
road[t1] = root;
sign[t1] = sign[root];
t1 = t2;
}
return root;
} int UnionRoot(int root1, int root2) {//基本的合并,一看就懂啦,看不懂就继续看- -
if (rec[root1] >= rec[root2]) {
road[root2] = root1;
rec[root1]++;
return root1;
} else {
road[root1] = root2;
rec[root2]++;
return root2;
}
} int main()
{
//freopen("input.txt", "r", stdin);
while (scanf("%d%d", &n, &m), n || m) {
ini();
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &node[i].a, &node[i].b, &node[i].c);
}
sort(node, node + m, comp);//基本的贪心思想
int ans = 0;
for (int i = 0; i < m; i++) {
int root1 = FindRoot(node[i].a);
int root2 = FindRoot(node[i].b);
if (root1 == root2 && sign[root1] == 0) {//当两个节点同属于一个集合的时候,看看这个集合已经形成环了没有,如果形成了,就不能加入了,反之则可以
ans += node[i].c;
sign[root1] = 1;
} else {
if (sign[root1] != 1 || sign[root2] != 1) {//两个节点分别属于不同的集合,因为合并的时候要考虑环的数量,所以当两个集合合并后新集合的环数量超过1也是不行的
ans += node[i].c;
int r = UnionRoot(root1, root2);
if (sign[root1] == 1 || sign[root2] == 1) {
sign[r] = 1;
}
}
}
}
printf("%d\n", ans);
}
return 0;
}
 
 
 
 
 

HDU - Pseudoforest的更多相关文章

  1. hdu 3367(Pseudoforest ) (最大生成树)

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

  2. hdu 3367 Pseudoforest (最大生成树 最多存在一个环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3367 Pseudoforest Time Limit: 10000/5000 MS (Java/Oth ...

  3. hdu 3367 Pseudoforest(最大生成树)

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  4. hdu 3367 Pseudoforest

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  5. hdu 3367 Pseudoforest (最小生成树)

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

  6. HDU 3367 Pseudoforest(Kruskal)

    Pseudoforest Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  7. hdu 3367 Pseudoforest(并查集)

    题意:有一种叫作Pseudoforest的结构,表示在无向图上,每一个块中选取至多包含一个环的边的集合,又称“伪森林”.问这个集合中的所有边权之和最大是多少? 分析:如果没有环,那么构造的就是最大生成 ...

  8. hdu 3367 Pseudoforest 最大生成树★

    #include <cstdio> #include <cstring> #include <vector> #include <algorithm> ...

  9. 【转载】图论 500题——主要为hdu/poj/zoj

    转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

随机推荐

  1. Jquery.Datatables dom表格定位

    Datatables会添加一些控制元素在表格的周围,比如默认状态下改变每页显示条数(l)的空间在左上角,即使搜索框(f)在右上角,表格的信息(i)显示在左下角,分页控件(p)显示在右下角. 这些控件在 ...

  2. securecrt 用心跳保持连接

    选项->会话->终端->发送协议NO-OP(P)

  3. SQL Server数据库大型应用解决方案总结(转载)

    转载地址:http://hb.qq.com/a/20120111/000216.htm 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的互联网应用,每天百万级甚至 ...

  4. python中的monkey-patching

    这个技巧我很少用过. 但知道无防. 在运行时改变函数或类的行为, 一般用猴子补丁,原类,装饰器都可以实现. #!/usr/bin/env python # -*- coding: utf-8 -*- ...

  5. 知乎大牛的关于JS解答

    很多疑惑一扫而空.... http://www.zhihu.com/question/35905242?sort=created JS的单线程,浏览器的多进程,与CPU,OS的对位. 互联网移动的起起 ...

  6. sqlplus链接数据库报ORA-09925: Unable to create audit trail file

    [localhost.localdomain]:[/oracle11/app/oracle11/product/11.2.0/dbhome_1/dbs]$ sqlplus / as sysdba SQ ...

  7. DateTime还是DateTimeOffset?Now还是UtcNow?

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:新年第一篇文章,就来谈谈关于时间的简单技术问题:该用DateTime还是DateTim ...

  8. 第十篇:扩展SOUI的控件及绘图对象(ISkinObj)

    尽管SOUI已经内置了大部分常用的控件,很显然内置控件很难满足各种应用的形式各异的需求. 因此只有提供足够的扩展性才能满足真实应用场景. 除了将系统尽可能的组件化外,SOUI在控件自绘(SWindow ...

  9. 小甲鱼PE详解之IMAGE_DOS_HEADER结构定义即各个属性的作用(PE详解01)

    (注:最左边是文件头的偏移量.) IMAGE_DOS_HEADER STRUCT {  +0h  WORD  e_magic  // Magic DOS signature MZ(4Dh 5Ah)   ...

  10. mysql 怎样清空一个数据库中的所有表

    转自:http://blog.csdn.net/zhangzhizhen1988/article/details/8432146 MySQL清空表是很重要的操作,也是最常见的操作之一,下面就为您详细介 ...