标签:
题目:
Pseudoforest |
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) |
Total Submission(s): 283 Accepted Submission(s): 122 |
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 |
Source “光庭杯”第五届华中北区程序设计邀请赛 暨 WHU第八届程序设计竞赛 |
Recommend lcy |
题目分析:
求有一个环的最大生成树。
1、要求最大生成树,这时候我们只需要把从小到大的排序函数改成从大到小排序即可。如:
bool cmp(Edge a,Edge b){
return a.weight > b.weight;
}
2、如何保证有一个环?
1)如果是两棵树在进行合并操作
两棵树都有环,不能进行合并操作。
如果只有一个数有环,可以进行合并操作。合并前先做一下标记。
如果都没有环,可以进行合并操作。
2)如果是是同一颗树在进行合并操作。
那么这棵树合并前必然不能有环。
代码如下:
/* * h.cpp * * Created on: 2015年3月11日 * Author: Administrator */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 10001; const int maxm = 100001; int father[maxn]; struct Edge{ int begin; int end; int weight; }edges[maxn*maxn]; int visited[maxn];//用来标记以某一结点为根节点的最大生成树中是否已经有环.如visited[i]=true.表示以i为根节点的最大生成树中已经有环 int find(int a){ if(a == father[a]){ return a; } return father[a] = find(father[a]); } /** * 求有一个环的最大生成树 */ int kruscal(int count){ int sum = 0; int i; for(i = 0 ; i < maxn ; ++i){ father[i] = i; } for(i = 0 ; i < count ; ++i){//注意这里的边的索引从0开始,从1开始这道题莫名其妙的WA int fa = find(edges[i].begin); int fb = find(edges[i].end); if(fa != fb){//如果是两棵树 if(visited[fa] == true && visited[fb] == true){//并且他们都已经有环 continue;//不能合并,继续拧下一次循环 } if(visited[fa] || visited[fb]){//如果其中有一棵树有环了.可以继续执行 visited[fa] = visited[fb] = true;//合并以后将这两棵树都标记位已经有环 } //合并操作 sum += edges[i].weight; father[fa] = fb; }else if(visited[fa] == false){//如果是同一棵树,并且还没有环 /** * 则能进行合并操作。为什么呢? * 同一棵树的合并操作,必然会导致又多出一个环. * 所以只有在原来还没有环的秦光霞才能继续拧合并 */ sum += edges[i].weight; visited[fa] = true; } } return sum; } bool cmp(Edge a,Edge b){ return a.weight > b.weight; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF,n){ memset(visited,false,sizeof(visited)); int i; for(i = 0 ; i < m ; ++i){ scanf("%d%d%d",&edges[i].begin,&edges[i].end,&edges[i].weight); } sort(edges,edges+m,cmp); printf("%d\n",kruscal(m)); } return 0; }
(hdu step 6.1.8)Pseudoforest(求有一个环的最大生成树)
标签:
原文地址:http://blog.csdn.net/hjd_love_zzt/article/details/44196529