hdu 5438 拓扑排序+并查集

remove的过程就像是拓扑排序,而最后统计sum可以用并查集,每个集合维护集合的size、sum。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <queue>
  6 using namespace std;
  7 
  8 typedef long long ll;
  9 const int INF = 999999999;
 10 const int N = 20000;
 11 const int M = 200000;
 12 int f[N];
 13 int sz[N];
 14 ll sum[N];
 15 int in[N];
 16 int head[N];
 17 queue<int> q;
 18 int n, m, e;
 19 
 20 struct Edge
 21 {
 22     int v, next;
 23 } edge[M << 1];
 24 
 25 void addEdge( int u, int v )
 26 {
 27     edge[e].v = v;
 28     edge[e].next = head[u];
 29     head[u] = e++;
 30 }
 31 
 32 void init()
 33 {
 34     while ( !q.empty() ) q.pop();
 35     e = 0;
 36     memset( in, 0, sizeof(in) );
 37     memset( head, -1, sizeof(head) );
 38     for ( int i = 1; i <= n; i++ )
 39     {
 40         f[i] = i;
 41         sz[i] = 1;
 42     }
 43 }
 44 
 45 int findf( int x )
 46 {
 47     if ( f[x] != x ) f[x] = findf( f[x] );
 48     return f[x];
 49 }
 50 
 51 void union_set( int x, int y )
 52 {
 53     x = findf(x), y = findf(y);
 54     if ( x != y )
 55     {
 56         f[x] = y;
 57         sz[y] += sz[x];
 58         sum[y] += sum[x];
 59     }
 60 }
 61 
 62 int main ()
 63 {
 64     int t;
 65     scanf("%d", &t);
 66     while ( t-- )
 67     {
 68         scanf("%d%d", &n, &m);
 69         init();
 70         for ( int i = 1; i <= n; i++ )
 71         {
 72             scanf("%I64d", &sum[i]);
 73         }
 74         while ( m-- )
 75         {
 76             int u, v;
 77             scanf("%d%d", &u, &v);
 78             in[u]++;
 79             in[v]++;
 80             addEdge( u, v );
 81             addEdge( v, u );
 82         }
 83         for ( int i = 1; i <= n; i++ )
 84         {
 85             if ( in[i] < 2 )
 86             {
 87                 q.push(i);
 88                 in[i] = INF;
 89             }
 90         }
 91         while ( !q.empty() )
 92         {
 93             int u = q.front();
 94             q.pop();
 95             for ( int i = head[u]; i != -1; i = edge[i].next )
 96             {
 97                 int v = edge[i].v;
 98                 in[v]--;
 99                 if ( in[v] < 2 )
100                 {
101                     q.push(v);
102                     in[v] = INF;
103                 }
104             }
105         }
106         for ( int i = 1; i <= n; i++ )
107         {
108             if ( in[i] > n ) continue;
109             for ( int j = head[i]; j != -1; j = edge[j].next )
110             {
111                 int v = edge[j].v;
112                 if ( in[v] > n ) continue;
113                 union_set( i, v );
114             }
115         }
116         ll ans = 0;
117         for ( int i = 1; i <= n; i++ )
118         {
119             if ( in[i] < n && f[i] == i && sz[i] % 2 == 1 )
120             {
121                 ans += sum[i];
122             }
123         }
124         printf("%I64d\n", ans);
125     }
126     return 0;
127 }

 

posted @ 2015-09-14 09:52  hxy_has_been_used  阅读(231)  评论(0编辑  收藏  举报