/*
上一道是根据割点判断可以割出多少个连通块来
对于每个图,割某个点,产生连通块的数量最大是多少.
一个割点编号对应一个剩余连通块的最大值.统计有几个最大值
how to 求连通块,怎么求每个连通块中点的个数
对v-dcc缩点之后,每个v-dcc的度数就是这个v-dcc连着几个割点
分别看每个连通块,设连通块中点的个数是cnt
如果连通块中没有割点,那么ans= c(cnt,2);
如果连通块中有割点
1.如果有n个v-dcc的度数为1,那么建n的出口
2.如果v-dcc的度数为2,说明这个v-dcc连接着两个割点,无论是v-dcc中的点还是割点坍塌,一定可以通过
别的点逃脱
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=2*510,M=510;
int h[N],e[M],ne[M],idx;
int low[N],dfn[N],tim;
int d[N];//每个v-dcc的度数
long long ans=0;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int cnt;
vector<int>v[N];
int num[N];//存储连通块中点的个数
void dfs(int u)
{
dfn[u]=1;
v[cnt].push_back(u);//节点u是第cnt个连通块中的点
int sum=0;//必须从0开始,最后再加1
// num[cnt]++;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!dfn[j])
sum++,dfs(j);
}
num[cnt]+=sum;//+=
}
int main()
{
int m,flag=1;
while(cin>>m,m)
{
int n=-1;
idx=0;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;cin>>a>>b;
n=max(a,n);
n=max(b,n);
add(a,b);
add(b,a);
}
// cout<<n<<endl;
for(int i=1;i<=n;i++)
if(!dfn[i])
cnt++,dfs(i);
cout<<cnt<<endl;//连通块的数量
for(int i=1;i<=cnt;i++)
cout<<num[i]<<endl;
cout<<"---"<<endl;
for(int i=1;i<=cnt;i++)
cout<<v[i].size()<<endl;
}
}