Link
显然相同位数的点是完全等价的。
那么我们可以固定(1)号店为根,剩下的就是一个二分图匹配的模型了。
可以一条一条确定,利用Hall定理check确定之后是否仍然有解。
其实我也不太明白。
#include<cstdio>
#include<cstring>
int min(int a,int b){return a<b? a:b;}
int max(int a,int b){return a>b? a:b;}
int n,m,ans,id[9],cnt[9],e[9][9],is[9];char s[9],t[9];
int check()
{
for(int i=0,x,y;i<(1<<m)-1;++i)
{
x=y=0;
for(int j=0;j<m;++j) if(i>>j&1) x+=cnt[j];
for(int j=0;j<m;++j) for(int k=j;k<m;++k) if((i>>j&1)|(i>>k&1)) y+=e[j][k];
if(y<x) return 0;
}
return 1;
}
int main()
{
scanf("%d",&n);
for(int i=n;i;i/=10) ++m;
for(int i=id[0]=1;i<m;++i) id[i]=id[i-1]*10;
for(int i=0;i<m;++i) cnt[i]=id[i+1]-id[i];
cnt[m-1]=n-id[m-1]+1;
for(int i=1,u,v;i<n;++i) scanf("%s",s),scanf("%s",t),u=strlen(s),v=strlen(t),++e[min(u,v)-1][max(u,v)-1];
if(!check()) return puts("-1"),0;
--cnt[0],is[0]=1,id[0]=2;
while(ans<n-1)
for(int i=0;i<m;++i)
if(is[i])
for(int j=0;j<m;++j)
if(cnt[j]&&e[min(i,j)][max(i,j)])
{
--cnt[j],--e[min(i,j)][max(i,j)];
if(check()) printf("%d %d
",id[i]-1,id[j]),++id[j],is[j]=1,++ans;
else ++cnt[j],++e[min(i,j)][max(i,j)];
}
}