[cf611H]New Year and Forgotten Tree

首先,來構造這棵樹的形態c++

稱位數相同的點爲一類點,從每一類點中任選一個點,具備如下性質:網絡

1.每一類中選出的點的導出子圖連通(是一顆樹)ide

2.每一條邊必然有一個端點屬於某一類中選出的點spa

(關於「如有解,必定存在上述這種形式的解」的證實可能比較困難,大概感性理解一下?)it

因爲類別不多(記爲$m=\lfloor\log_{10}n\rfloor+1$),$o(m^{m-2})$或$o{\frac{(m+1)m}{2}\choose m-1}$暴力肯定這$m$類點中選出的點的樹形態(實際差不了多少),接下來每一條邊至關於能夠使邊端點中的一類未在連通塊中加入連通塊,即若是記$s_{x}$表示$x$類點剩餘的點數量,以後每一條邊至關於選擇$s_{x}$或$s_{y}$減少1class

很明顯是一個網絡流的模型,判一下是否滿流便可,複雜度大概可過queue

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
  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\n",ansE[i].fi,ansE[i].se);
122     }
123 } 
View Code
相關文章
相關標籤/搜索