[cf611H]New Year and Forgotten Tree

首先,来构造这棵树的形态

称位数相同的点为一类点,从每一类点中任选一个点,具有以下性质:

1.每一类中选出的点的导出子图连通(是一颗树)

2.每一条边必然有一个端点属于某一类中选出的点

(关于“若有解,一定存在上述这种形式的解”的证明可能比较困难,大概感性理解一下?)

由于类别很少(记为$m=lfloorlog_{10}n floor+1$),$o(m^{m-2})$或$o{frac{(m+1)m}{2}choose m-1}$暴力确定这$m$类点中选出的点的树形态(实际差不了多少),接下来每一条边相当于可以使边端点中的一类未在连通块中加入连通块,即如果记$s_{x}$表示$x$类点剩余的点数量,之后每一条边相当于选择$s_{x}$或$s_{y}$减小1

很明显是一个网络流的模型,判一下是否满流即可,复杂度大概可过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define M 7
  5 #define oo 0x3f3f3f3f
  6 #define fi first
  7 #define se second
  8 struct ji{
  9     int nex,to,len;
 10 }edge[M*M*M];
 11 queue<int>q;
 12 vector<pair<int,int> >ansE;
 13 int V,E,n,m,head[M*M],len[N],a[M][M],id[M][M],tot[M],pos[M],now[M],f[M],d[M*M],work[M*M];
 14 char s1[M],s2[M];
 15 int find(int k){
 16     if (k==f[k])return k;
 17     return find(f[k]);
 18 }
 19 void add(int x,int y,int z){
 20     edge[E].nex=head[x];
 21     edge[E].to=y;
 22     edge[E].len=z;
 23     head[x]=E++;
 24     if (E&1)add(y,x,0);
 25 }
 26 bool bfs(){
 27     memset(d,oo,sizeof(d));
 28     d[0]=0;
 29     q.push(0);
 30     while (!q.empty()){
 31         int k=q.front();
 32         q.pop();
 33         for(int i=head[k];i!=-1;i=edge[i].nex)
 34             if ((edge[i].len)&&(d[edge[i].to]==oo)){
 35                 d[edge[i].to]=d[k]+1;
 36                 q.push(edge[i].to);
 37             }
 38     }
 39     return d[V+m+1]<oo;
 40 }
 41 int dfs(int k,int s){
 42     if (k>V+m)return s;
 43     for(int &i=work[k];i!=-1;i=edge[i].nex)
 44         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
 45             int p=dfs(edge[i].to,min(s,edge[i].len));
 46             if (p){
 47                 edge[i].len-=p;
 48                 edge[i^1].len+=p;
 49                 return p;
 50             }
 51         }
 52     return 0;
 53 }
 54 int dinic(){
 55     int k,ans=0;
 56     while (bfs()){
 57         memcpy(work,head,sizeof(work));
 58         while (k=dfs(0,oo))ans+=k;
 59     }
 60     return ans;
 61 }
 62 bool dfs(int k,int x,int y){
 63     if (k>=m){
 64         E=0;
 65         memset(head,-1,sizeof(head));
 66         for(int i=1;i<=m;i++)
 67             for(int j=i;j<=m;j++){
 68                 add(0,id[i][j],a[i][j]);
 69                 add(id[i][j],V+i,oo);
 70                 add(id[i][j],V+j,oo);
 71             }
 72         for(int i=1;i<=m;i++)add(V+i,V+m+1,tot[i]);
 73         if (dinic()==n-m){
 74             for(int i=1;i<=m;i++)
 75                 for(int j=i;j<=m;j++)
 76                     for(int k=head[id[i][j]];k!=-1;k=edge[k].nex)
 77                         if (edge[k].to>V){
 78                             int p=edge[k].to-V;
 79                             for(int l=edge[k].len;l<oo;l++)ansE.push_back(make_pair(++now[p],pos[i+j-p]));
 80                         }
 81             return 1;
 82         }
 83         return 0;
 84     }
 85     for(int i=x;i<=m;i++)
 86         for(int j=y;j<=m;j++)
 87             if ((a[i][j])&&(find(i)!=find(j))){
 88                 int ii=find(i);
 89                 f[ii]=j;
 90                 a[i][j]--;
 91                 ansE.push_back(make_pair(pos[i],pos[j]));
 92                 if (dfs(k+1,i,j))return 1;
 93                 f[ii]=ii;
 94                 a[i][j]++;
 95                 ansE.pop_back();
 96             }
 97     return 0;
 98 }
 99 int main(){
100     scanf("%d",&n);
101     for(int i=1;i<n;i++){
102         scanf("%s%s",s1,s2);
103         int x=strlen(s1),y=strlen(s2);
104         if (x>y)swap(x,y);
105         a[x][y]++;
106     }
107     for(int i=1;i<=n;i++){
108         len[i]=len[i/10]+1;
109         tot[len[i]]++;
110     }
111     m=len[n];
112     for(int i=1;i<=m;i++)tot[i]--;
113     pos[1]=1;
114     for(int i=2;i<=m;i++)pos[i]=pos[i-1]*10;
115     memcpy(now,pos,sizeof(now));
116     for(int i=1;i<=m;i++)f[i]=i;
117     for(int i=1;i<=m;i++)
118         for(int j=i;j<=m;j++)id[i][j]=++V;
119     if (!dfs(1,1,1))printf("-1");
120     else{
121         for(int i=0;i<ansE.size();i++)printf("%d %d
",ansE[i].fi,ansE[i].se);
122     }
123 } 
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14383775.html