Question:
Problem Description
In graph theory, a pseudo forest is an undirected graph in which every connected component has at most one cycle. the maximal pseudo doforests of G are the pseudo forest subgraphs of G that are not contained within any larger pseudo doforest 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
Source
The fifth Central China North District Invitational Design Competition and WHU Eighth Program Design Competition
Analysis and Summary:
This question has been understood for a while before we can understand it. To give a graph, we need to produce the largest pseudo forest. The so-called pseudo forest refers to a subgraph of the graph, each connected component of this subgraph can have only one ring, and the sum of the ownership values of this subgraph is the largest. This is the so-called pseudo forest.
The process is similar to that of kruskal for the Minimum Spanning Tree. Do not directly find the maximum spanning tree. At the beginning, I used the kruskal algorithm to find the maximum Spanning Tree of the graph, then add the largest edge to each vertex to form a ring. But WA has to vomit blood.
The correct method is similar to the maximization spanning tree, but it is slightly changed because each connected component allows a loop. Therefore, when merging two trees, to determine whether the two trees have loopback loops, if both trees have loopback loops, the two trees obviously cannot be merged. If only one tree has loopback loops, they can be merged, then mark it. If neither of them has a loop, merge them directly.
If two vertices belong to the same tree, determine whether there is a loop in the tree. If not, a loop is allowed. You can link the two points and mark them.
For more information, see the code.
Code:
[Cpp]
# Include <cstdio>
# Include <cstring>
# Include <algorithm>
# Define N 10005
Using namespace std;
Struct Edge {
Int u, v, val;
Friend bool operator <(const Edge & a, const Edge & B ){
Return a. val> B. val;
}
} Arr [N * 10];
Int f [N], rank [N], vis [N], n, m;
Void init (){
For (int I = 0; I <= n; ++ I)
F [I] = I, rank [I] = 0;
}
Int find (int x ){
Int I, j = x;
While (j! = F [j]) j = f [j];
While (x! = J) {I = f [x]; f [x] = j; x = I ;}
Return j;
}
Void Union (int x, int y ){
Int a = find (x), B = find (y );
If (a = B) return;
If (rank [a]> rank [B])
F [B] =;
Else {
If (rank [a] = rank [B])
++ Rank [B];
F [a] = B;
}
}
Int main (){
While (~ Scanf ("% d", & n, & m )){
If (! N &&! M) break;
For (int I = 0; I <m; ++ I)
Scanf ("% d", & arr [I]. u, & arr [I]. v, & arr [I]. val );
Init ();
Sort (arr, arr + m );
Memset (vis, 0, sizeof (vis ));
Long ans = 0;
For (int I = 0; I <m; ++ I ){
Int a = find (arr [I]. u), B = find (arr [I]. v );
If (! = B ){
If (vis [a] & vis [B]) continue; // both have Loops
If (vis [a] | vis [B]) vis [a] = vis [B] = 1;
Ans + = arr [I]. val;
Union (a, B );
}
Else if (! Vis [a]) {// although it is the same number of workers, there is no ring
Union (a, B );
Vis [a] = 1;
Ans + = arr [I]. val;
}
}
Printf ("% lld \ n", ans );
}
Return 0;
}