题意
并查集的简单使用
因为没有进行复杂度分析,想到哪写到哪,就照着最简单的思路写下去了
本以为自己这么写完会MLE或者TLE,结果一发入魂,实在是太开心了!
所以说,不要怂,就是肝
小小的总结一下
①题目中ID经常是k位数字,如果数字不大,完全可以用int来存,不必用string,但要注意0001会被存储为1,输出的时候要进行格式控制
②此题中开了10005的数组表示个体,但一直在想f[i]==i,代表i是根节点,可有那么多题目中没有出现过的数据,我该怎么办啊啊啊啊!看了网友的博客,他用了一个visit数组记录,醍醐灌顶
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int estate[10005];
int area[10005];
int f[10005];
int visit[10005]={0};
struct Family{
int num=0;
int id;
double es=0;
double ar=0;
};
Family family[10005];
int myfind(int x){
if(f[x]!=x)
return myfind(f[x]);
return x;
}
bool cmp(const Family& a,const Family& b){
if(a.ar==b.ar){
return a.id<b.id;
}else{
return a.ar>b.ar;
}
}
void myunion(int x,int y){
if(x==-1||y==-1) return;
int fx=myfind(x);
int fy=myfind(y);
if(fx!=fy){
if(fx<fy){
f[fy]=fx;
}else{
f[fx]=fy;
}
}
}
int main(){
int n;
for(int i=0;i<10005;i++){
f[i]=i;
}
memset(estate,0,sizeof(estate));
memset(area,0,sizeof(area));
scanf("%d",&n);
for(int i=0;i<n;i++){
int id,father,mother,k,x,y;
scanf("%d%d%d%d",&id,&father,&mother,&k);
vector<int>child;
for(int j=0;j<k;j++){
int temp;
scanf("%d",&temp);
child.push_back(temp);
}
scanf("%d%d",&x,&y);
estate[id]=x;
area[id]=y;
myunion(id,father);
myunion(id,mother);
visit[id]=1;
visit[father]=1;
visit[mother]=1;
for(int j=0;j<child.size();j++){
myunion(id,child[j]);
visit[child[j]]=1;
}
}
for(int i=0;i<10005;i++){
if(visit[i]==1){
family[myfind(i)].num++;
family[myfind(i)].es+=estate[i];
family[myfind(i)].ar+=area[i];
//printf("%d %d\n",family[i].es,family[i].ar);
}
}
int cnt=0;
for(int i=0;i<10005;i++){
if(family[i].num!=0){
cnt++;
family[i].id=i;
family[i].es/=family[i].num;
family[i].ar/=family[i].num;
}
}
sort(family,family+10005,cmp);
printf("%d\n",cnt);
for(int i=0;i<10005;i++){
if(family[i].num!=0){
printf("%04d %d %.3f %.3f\n",family[i].id,family[i].num,family[i].es,family[i].ar);
}
}
return 0;
}