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 ;
}
相关文章推荐
- HDU 3367 Pseudoforest(伪森林)(并查集)
- hdu-3367 Pseudoforest(伪森林, kruskal变形)
- HDU 3367 Pseudoforest(kruskal最大生成树变形)
- HDU 3367 Pseudoforest(Kruskal)
- hdu 3367 Pseudoforest【伪森林】
- hdu-3367-Pseudoforest-并查集
- hdu 3367 Pseudoforest (伪森林) not 最大生成树 解题报告
- hdu 3367 Pseudoforest(伪森林)
- Hdu 3367 Pseudoforest(并查集)
- hdu 3367 Pseudoforest(并查集)
- Pseudoforest【伪森林】+【最大生成树】+【并查集判断是否成环】
- hdu 3367 Pseudoforest(并查集)
- HDU 3367 Pseudoforest (并查集)
- HDU 3367 Pseudoforest(Kruskal)
- hdoj 3367 Pseudoforest 【伪森林】 【并查集判断环 + 最大生成树】
- HDU 3367 Pseudoforest (最小生成树,并查集)
- hdu 3367 Pseudoforest (并查集)
- hdu 3367 伪森林(kruskal)
- HDU 3367 Pseudoforest 最小生成树
- (使用树结构来支持并查集操作8.4.2)POJ 2236 Wireless Network(判断两个元素是否在同一个集合&&有条件的合并)