zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    Parallel Programming指南
    使用Autofac IOC组织多项目应用程序
    对SQL Server 2008 R2感兴趣StreamInsight特性
    跨平台团队协作项目源码管理软件Mercurial客户端TortoiseHg
    Windows Server AppFabric正式发布
    Windows NLB搭配IIS的ARR搭建高可用环境
    使用VS2010的Database 项目模板统一管理数据库对象
    Fityk曲线拟合工具
    Windows Server AppFabric Beta 2 for For Vistual Studio 2010已经发布
    Visual Studio 2010快速参考指南里头的Scrum海报
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14383775.html
Copyright © 2011-2022 走看看