题目大意:求并查集中集合的个数,及每个集合的详细信息
解题关键:只要不进行unite,集合的根是不会变化的。
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<iostream> using namespace std; struct node{ int id,cnt,area; }pe[10002]; struct nod{ int id,num,cnt,area; double avcnt,avar; }pa[10002]; bool vis[10002]; int par[10002]; int find1(int x){ if(x==par[x]) return x; else return par[x]=find1(par[x]); } bool cmp(nod x,nod y){ if(x.avar==y.avar) return x.id<y.id; else return x.avar>y.avar; } void unite(int x,int y){ x=find1(x); y=find1(y); if(x==y) return; else par[x]=y;//为什么这里改变一下会有变化??? } int main(){ int n; scanf("%d",&n); for(int i=0;i<10002;i++){ par[i]=i; } for(int i=0;i<n;i++){ int t1,t2,t3; scanf("%d%d%d",&t1,&t2,&t3); vis[t1]=true; if(t2!=-1){ unite(t1, t2); vis[t2]=true; } if(t3!=-1){ unite(t1,t3); vis[t3]=true; } int k; scanf("%d",&k); for(int j=0;j<k;j++){ int temp; scanf("%d",&temp); unite(t1,temp); vis[temp]=true; } pe[i].id=t1; int t4,t5; scanf("%d%d",&t4,&t5); pe[i].cnt=t4; pe[i].area=t5; } for(int i=0;i<n;i++){ int id=find1(pe[i].id); //id=find1(id); pa[id].cnt+=pe[i].cnt; pa[id].area+=pe[i].area; // pa[id].num++; } for(int i=0;i<=9999;i++){//这里是核心 if(vis[i]){ //int t=par[i]=find1(i); int t=find1(i); if(!pa[t].num){ pa[t].id=i; } pa[t].num++; pa[t].avar=pa[t].area*1.0/pa[t].num;//这里其实是重复覆盖的 pa[t].avcnt= pa[t].cnt*1.0/pa[t].num; } } sort(pa,pa+10000,cmp); int ans=0; for(int i=0;i<10000;i++){ if(pa[i].num){ ans++; } //else break; } printf("%d ",ans); for(int i=0;i<ans;i++){ if(pa[i].num){ printf("%04d %d %.3lf %.3lf ",pa[i].id,pa[i].num,pa[i].avcnt,pa[i].avar); } } }