bzoj 1098

对于关系,看其是否是“等价关系”,即满足:自反,传递,对称。

如果是可以用并查集来连接等价类。

这道题是求原图补集的联通快个数,考虑原图度最少的点(由鸽巢原理,最多为2*e/n个)。

先将未与其连边的点并在一个集合中,然后再用剩下的点暴力,每次O(n),最多暴力O(2*e/n)次,所以总的复杂度是O(e)的。

 1 /**************************************************************
 2     Problem: 1098
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:8932 ms
 7     Memory:31140 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <cstring>
12 #include <vector>
13 #include <algorithm>
14 #define maxn 100010
15 using namespace std;
16  
17 int n, m;
18 int dgr[maxn];
19 vector<int> g[maxn], stk;
20 int fa[maxn], sz[maxn];
21 bool mark[maxn];
22  
23  
24 void init() {
25     for( int i=1; i<=n; i++ ) fa[i]=i;
26 }
27 int find( int a ) {
28     return a==fa[a] ? a : fa[a]=find(fa[a]);
29 }
30 void unon( int a, int b ) {
31     fa[find(a)] = find(b);
32 }
33  
34 int main() {
35     scanf( "%d%d", &n, &m );
36     for( int i=1,u,v; i<=m; i++ ) {
37         scanf( "%d%d", &u, &v );
38         g[u].push_back( v );
39         g[v].push_back( u );
40         dgr[u]++, dgr[v]++;
41     }
42     int mu=1;
43     init();
44     for( int u=2; u<=n; u++ ) if( dgr[u]<dgr[mu] ) mu=u;
45  
46     for( int t=0; t<g[mu].size(); t++ ) mark[g[mu][t]]=true;
47     for( int u=1; u<=n; u++ ) if( !mark[u] ) unon(u,mu);
48     for( int t=0; t<g[mu].size(); t++ ) mark[g[mu][t]]=false;
49  
50     for( int t=0; t<g[mu].size(); t++ ) stk.push_back( g[mu][t] );
51     for( int i=0; i<stk.size(); i++ ) {
52         int u=stk[i];
53  
54         for( int t=0; t<g[u].size(); t++ ) mark[g[u][t]] = true;
55         for( int v=1; v<=n; v++ ) if( !mark[v] ) unon(u,v);
56         for( int t=0; t<g[u].size(); t++ ) mark[g[u][t]] = false;
57     }
58     for( int u=1; u<=n; u++ )
59         sz[find(u)]++;
60     vector<int> ans;
61     for( int u=1; u<=n; u++ )
62         if( fa[u]==u ) ans.push_back(sz[u]);
63     sort( ans.begin(), ans.end() );
64     printf( "%d
", ans.size() );
65     for( int t=0; t<ans.size(); t++ )
66         printf( "%d ", ans[t] );
67     printf( "
" );
68 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4344166.html