Problem H
Time Limit : 10000/5000ms (Java/Other) Memory Limit :65536/65536K (Java/Other)
Total Submission(s) : 1 Accepted Submission(s) : 1
Problem Description
In graph theory, apseudoforest is an undirected graph in which every connected component has atmost one cycle. The maximal pseudoforests of G are the pseudoforest subgraphsof G that are not contained within any larger pseudoforest of G. A pesudoforestis larger than another if and only if the total value of the edges is greaterthan another one’s.<br><br>
Input
The input consists of multipletest 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 vertexesand the number of the edges. The next m lines, each line consists of threeintegers, 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 multipleedges.<br>The last test case is followed by a line containing two zeros,which means the end of the input.<br>
Output
Output the sum of the value ofthe edges of the maximum pesudoforest.<br>
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
算法分析:
题意:
这是百度上的题意:在图论中,如果一个森林中有很多连通分量,并且每个连通分量中至多有一个环,那么这个森林就称为伪森林。现在给出一个森林,求森林包含的最大的伪森林,其大小通过所有边的权值之和来比较。
我的理解就是:求一个环的最大生成树。
kruskal变形:
1. 从大到小排序
2. 合并时,如果会生成两个环,则不合并,需要数组标记。
1)如果是两棵树在进行合并操作
两棵树都有环,不能进行合并操作。
如果只有一个数有环,可以进行合并操作。合并前先做一下标记。
如果都没有环,可以进行合并操作。
2)如果是是同一颗树在进行合并操作。
那么这棵树合并前必然不能有环。
代码实现:
#include<bits/stdc++.h> using namespace std; int fa[10010]; bool vis[10010]; struct node { int x,y,v; }a[100005]; int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } int cmp(node b,node c)//这里要从大到小排序 { return b.v>c.v; } int main() { int n,m; while( scanf("%d%d",&n,&m)!=EOF&&(n||m)) { int num=0; for(int i=0;i<=n;i++) fa[i]=i; memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); a[num].x=x; a[num].y=y; a[num].v=v; num++; } sort(a,a+num,cmp); int ans=0; for(int i=0;i<num;i++) { int r1=find(a[i].x); int r2=find(a[i].y); if(r1!=r2)//表示两棵树 { if(vis[r1]==1&&vis[r2]==1)//如果两棵树都有环,则不能合并 continue; if(vis[r1]||vis[r2])//如果其中有一个有环,合并 { vis[r1]=vis[r2]=1;//标记有环 } fa[r1]=r2; ans+=a[i].v; } else if(!vis[r1])//如果在一棵树内,且没有环 { //不能进行合并操作,不然会产生环,加上权值即可 ans+=a[i].v; vis[r1]=1; } } printf("%d\n",ans); } return 0; }