CF611H New Year and Forgotten Tree

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)];
		    }
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12236389.html