// 配列は全て1から始まる扱いで。 #include #include using namespace std; class Masato{ private : int blocks; int *down_of; int *up_of; void Clear(); void BreakUpper(int trg); //これより上を床にばら撒く。 bool IsInSamePile(int a,int b); bool IsUpperOf(int a,int b);//なんて胡散臭い英語だ。 int GetTopOf(int trg); public : Masato(); void Init(int blocks); void Operation(int from,int onto); void PrintAnswer(); }; Masato::Masato(){ blocks=0; down_of = NULL; up_of = NULL; } void Masato::Init(int blocks){ Clear(); this->blocks = blocks; down_of = new int[blocks+1]; up_of = new int[blocks+1]; // bad_allocに期待。 for(int i=1;i<=blocks;i++){ down_of[i]=up_of[i]=0; } } void Masato::Clear(){ if(down_of) delete[] down_of; if(up_of) delete[] up_of; blocks =0; } void Masato::BreakUpper(int trg){ int now = up_of[trg]; int next; up_of[trg]=0; while(now != 0){ next = up_of[now]; up_of[now]=0; down_of[now]=0; now = next; } } bool Masato::IsInSamePile(int a,int b){ return IsUpperOf(a,b)||a==b||IsUpperOf(b,a); } bool Masato::IsUpperOf(int a,int b){ int now; now = b; while(true){ now = up_of[now]; if(now == 0) return false; if(now == a) return true; } } int Masato::GetTopOf(int trg){ if(up_of[trg]==0) return trg; return GetTopOf(up_of[trg]); } void Masato::Operation(int from,int onto){ if(from == onto) return; if(onto == 0){ //もともと床にある。 if(down_of[from] == 0) return; }else if(IsUpperOf(from,onto)){ return; } BreakUpper(from); if(onto == 0){ down_of[from]=0; }else{ int top; top = GetTopOf(onto); up_of[top] = from; up_of[down_of[from]]=0; down_of[from]=top; } } int CompareInt(const void *a,const void *b){ return *((int *)a)-*((int*)b); } void Masato::PrintAnswer(){ int piles = 0; int *sizes = new int[blocks+1]; bool *searched = new bool[blocks+1]; for(int i=1;i<=blocks;i++){ searched[i]=false; } for(int i=1;i<=blocks;i++){ if(searched[i]) continue; piles++; sizes[piles]=1; searched[i]=true; for(int j=i+1;j<=blocks;j++){ if(!IsInSamePile(i,j)) continue; searched[j]=true; sizes[piles]++; } } qsort(sizes+1,piles,sizeof(int),CompareInt); for(int i=1;i<=piles;i++){ cout << sizes[i] <> blocks; if(blocks==0) break; m.Init(blocks); while(true){ cin >> i; cin >> j; if(i==0 && j==0) break; m.Operation(i,j); } m.PrintAnswer(); } return 0; }