您的位置:首页 > 其它

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

2017-03-12 23:44 513 查看

Pseudoforest

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

Total Submission(s): 2880    Accepted Submission(s): 1129


[align=left]Problem Description[/align]
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.

 

[align=left]Input[/align]
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.

 

[align=left]Output[/align]
Output the sum of the value of the edges of the maximum pesudoforest.

 

[align=left]Sample Input[/align]

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

 

[align=left]Sample Output[/align]

3
5

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

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

代码如下:

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
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<b.c;
}
};

int n , m ;
int f[MAX] ;
bool vis[MAX] ;
int find(int x)
{
int p = x ;
while(p!=f[p])
{
p = f[p] ;
}
while(x!=f[x])
{
x = f[x];
f[x] = p ;

}
return p ;
}

void init(int n )
{
for(int i = 0 ; i <= n ; ++i)
{
f[i] = i ;
vis[i] = false ;
}
}
int main()
{
priority_queue<Edge,vector<Edge> , 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 ;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息