C - News Distribution (并查集)

Example
input
 
7 5
3 2 5 4
0
2 1 2
1 1
2 6 7
output
 
4 4 1 4 4 2 2 


思路:简单来讲,就是用并查集求每个点所在连通块的大小,有两种写法......


写法一:用并查集合并所给边之后,再扫一遍标记每个联通块大小,最后输出,这个写法比较好理解,但是复杂度略高......


 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define quick ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 5 const int inf=99999999;
 6 const int mod=1e9+7;
 7 const int maxn=5e5+5;
 8 int book[maxn];
 9 int f[maxn];
10 void init(int n)
11 {
12     for(int i=0;i<=n+1;i++)
13         f[i]=i;
14 }
15 int getf(int v)
16 {
17     if(f[v]==v)
18         return v;
19     else
20     {
21         f[v]=getf(f[v]);
22         return f[v];
23     }
24 }
25 void merge(int u,int v)
26 {
27     int t1=getf(u);
28     int t2=getf(v);
29     if(t1!=t2)
30         f[t2]=t1;
31 }
32 int main()
33 {
34     quick;
35     int n,m;
36     cin>>n>>m;
37     for(int i=0;i<=n;i++)
38         f[i]=i;
39     int k;
40     int temp,num;
41     for(int i=0;i<m;i++)
42     {
43         cin>>k;
44         if(!k)
45             continue;
46         cin>>temp;
47         k--;
48         for(int i=0;i<k;i++)
49         {
50             cin>>num;
51             merge(temp,num);
52         }
53     }
54     for(int i=1;i<=n;i++)
55         book[f[i]=getf(f[i])]++;
56     for(int i=1;i<n;i++)
57         cout<<book[f[i]]<<" ";
58     cout<<book[f[n]];
59     return 0;
60 }
 
    
   

写法二:用个size数组记录每个联通块大小,随并查集边合并的时候刷新,最后直接输出......



 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define quick ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 5 const int inf=99999999;
 6 const int mod=1e9+7;
 7 const int maxn=5e5+5;
 8 int f[maxn];
 9 int size[maxn];
10 void init(int n)
11 {
12     for(int i=1;i<=n+1;i++)
13     {
14         f[i]=i;
15         size[i]=1;
16     }
17 }
18 int getf(int v)
19 {
20     if(f[v]==v)
21         return v;
22     else
23     {
24         f[v]=getf(f[v]);
25         return f[v];
26     }
27 }
28 void merge(int u,int v)
29 {
30     u=getf(u);
31     v=getf(v);
32     if(u==v)
33         return ;
34     if(size[u]<size[v])
35         swap(u,v);//让u所在联通块变成大的 
36     f[v]=u;
37     size[u]+=size[v];//将v的连通块合并到u上 
38 }
39 int main()
40 {
41     quick;
42     int n,m;
43     cin>>n>>m;
44     init(n);
45     int k;
46     int temp,num;
47     for(int i=0;i<m;i++)
48     {
49         cin>>k;
50         if(!k)
51             continue;
52         cin>>temp;
53         k--;
54         for(int i=0;i<k;i++)
55         {
56             cin>>num;
57             merge(temp,num);
58         }
59     }
60     for(int i=1;i<n;i++)
61         cout<<size[getf(i)]<<" ";
62     cout<<size[getf(n)];
63     return 0;
64 }
 
   


猜你喜欢

转载自www.cnblogs.com/xwl3109377858/p/10890580.html