最大伪森林:原图的一个子图,在子图的各个连通分量中至多有一个环,且各边权和最大。
方法:kruskal,只是排序按边权从大到小,合并的时候注意判断是否构成多个环。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int N = 10000; 8 const int M = 100000; 9 int f[N]; 10 bool cycle[N]; 11 12 struct Edge 13 { 14 int u, v, w; 15 bool operator < ( const Edge & o ) const 16 { 17 return w > o.w; 18 } 19 } edge[M]; 20 21 int findf( int x ) 22 { 23 if ( f[x] != x ) f[x] = findf(f[x]); 24 return f[x]; 25 } 26 27 int main () 28 { 29 int n, m; 30 while ( scanf("%d%d", &n, &m) != EOF ) 31 { 32 if ( n == 0 && m == 0 ) break; 33 for ( int i = 0; i < m; i++ ) 34 { 35 scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); 36 } 37 for ( int i = 0; i < n; i++ ) 38 { 39 f[i] = i; 40 } 41 sort( edge, edge + m ); 42 memset( cycle, 0, sizeof(cycle) ); 43 int sum = 0; 44 for ( int i = 0; i < m; i++ ) 45 { 46 int u = edge[i].u, v = edge[i].v, w = edge[i].w; 47 u = findf(u), v = findf(v); 48 if ( u == v ) 49 { 50 if ( !cycle[u] ) 51 { 52 sum += w; 53 cycle[u] = 1; 54 } 55 } 56 else 57 { 58 if ( cycle[u] && cycle[v] ) 59 { 60 continue; 61 } 62 sum += w; 63 f[u] = v; 64 if ( cycle[u] || cycle[v] ) 65 { 66 cycle[v] = 1; 67 } 68 } 69 } 70 printf("%d\n", sum); 71 } 72 return 0; 73 }
时间: 2024-10-17 00:20:37