hdu 3367 Pseudoforest 伪森林 题目很难懂,模仿kruskal,并查集检查两个节点是否是一个环

Pseudoforest

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2880    Accepted Submission(s): 1129


Problem 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
 
题目的大意就是,给定一个图G,让你求G的一个子图,这个图要满足最大的伪森林,最大定义为伪森林的所有的边权值加起来最大。伪森林就是每个联通分量有且仅有一个环的图。

用kruskal算法,每次使用优先队列取出权值最大的边,然后用并查集检查加入这条边的是否形成环,如果形成环,则标记这条边的两个节点属于一个环,如果不形成环,并且这条边的两个顶点分别在两个不同的环中时,则不能加入这条边,因为加入这条边就不满足伪森林的定义,如果这条边的两个顶点只有一个在环中,则加入这条边,并修改不在环中的顶点为在环中。

代码如下:

#include 
#include 
#include 
#include 
using namespace std ;

const int MAX = 100100 ;

typedef struct Edge{
	int u , v , c ;
}Edge;

struct cmp{
	
	bool operator()(const Edge &a , const Edge &b)
	{
		return a.c , cmp> que ;
	while(~scanf("%d%d",&n,&m))
	{
		
		if(m == 0 && n == 0)
		{
			return 0 ;
		}
		init(n) ;
		
		for(int i = 0 ; i < m ; ++i)
		{
			int u , v, c;
			Edge t ;
			scanf("%d%d%d",&u,&v,&c);
			t.u = u , t.v = v , t.c = c ;
			que.push(t) ;
		}
		int cost = 0 ;
		for(int i = 0 ; i < m ; ++i)
		{
			Edge t = que.top();
			int x = find(t.u) , y = find(t.v) ;
			if(x != y )
			{
				if(!vis[x] && !vis[y])
				{
					f[x] = y ;
					cost += t.c ;
				}
				else if(!vis[x] || !vis[y])
				{
					vis[y] = true ;
					vis[x] = true ;
					f[x] = y ;
					cost+=t.c ;
				}
			}
			else
			{
				if(!vis[x])
				{
					cost += t.c;
					vis[x] =  1 ;
				}
				
			}
			
			que.pop();
		}
		printf("%d\n",cost) ;
	}
	return 0 ;
} 








你可能感兴趣的:(并查集,生成树,图论,Kruskal)