标签:结点 查集 压缩 路径 2069 网络分析 权值 include AcWing
考察:并查集
思路:
很容易想到用并查集的根节点代表此集合的权值和.但是注意在结点合并的时候,会出现本不属于这里的权值.被路径压缩加到子结点上.
这里有两种处理方式:
一、建立虚点. 在x,y之上建立一个结点s,在路径压缩时就不会合并到y集合的权值k.
二、特殊处理x结点权值,在x权值和上减去y的权值和.
但是注意:直接这么路径压缩会使得1 2 4(样例)权值和计算错误.我们第一次合并可能会将r,p[x]的权值传递给x,但后面查询x的父节点后,又会将r的权值和再累加到x里.所以根据并查集压缩路径的结果,当枝条结点只有两个时,我们不进行权值合并,那么最后x的权值和结果是f[x]+f[p[x]].如果>2个,要符合前面的算式我们需要f[x] = f[x]+f[p[x]]因此路径压缩时可以累加父节点的权值.
最后还有一种特殊情况,就是p[x] = x.此时累加会使得结果重复.
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N = 10010; 6 int p[N<<1],n,m,f[N<<1],idx; 7 int findf(int x) 8 { 9 if(x!=p[x]) 10 { 11 int pa = findf(p[x]); 12 if(pa!=p[x]) f[x]+=f[p[x]]; 13 p[x] = pa; 14 } 15 return p[x]; 16 } 17 void merge(int a,int b) 18 { 19 int pa = findf(a),pb = findf(b); 20 if(pa==pb) return; 21 p[pa] = ++idx; 22 p[pb] = idx; 23 } 24 void add(int x,int score) 25 { 26 int pa = findf(x); 27 f[pa]+=score; 28 } 29 int main() 30 { 31 scanf("%d%d",&n,&m); 32 idx = n; 33 for(int i=1;i<=n*2;i++) p[i] = i; 34 while(m--) 35 { 36 int op,x,y; 37 scanf("%d%d%d",&op,&x,&y); 38 if(op==1) merge(x,y); 39 else add(x,y); 40 } 41 for(int i=1;i<=n;i++) 42 { 43 if(p[i]!=i) f[i]+=f[findf(i)]; 44 printf("%d ",f[i]); 45 } 46 return 0; 47 }
标签:结点,查集,压缩,路径,2069,网络分析,权值,include,AcWing 来源: https://www.cnblogs.com/newblg/p/14665350.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。