zoukankan      html  css  js  c++  java
  • [cf1615G]Maximum Adjacent Pairs

    考虑所有极长的0,对其长度分类讨论——

    1.若其长度为$2m+1$,总是将首/尾与相邻的非0元素配对,其余元素配成$m$对

    同时,若首尾中某一个元素对应的$k$已经出现,那么必然与另一个配对

    2.若其长度为$2m$,总是配成$m$对或将首/尾均与相邻的非0元素配对,其余元素配成$m-1$对

    同时,若首尾中某一个元素对应的$k$已经出现,那么必然直接配成$m$对

    处理完必然的情况后,不妨仅考虑第1种情况的选择——

    将首尾相邻的非0元素连边,即对每一条边选择一个端点并最大化选择的集合

    显然每一个连通块是独立的,考虑其中一个连通块:

    1.若其为树,任选一点为根并对每一条边选择儿子,即仅有根未被选择

    注意到根是任意的,且由于边数$<$点数,因此不可能使所有点均被选择(已经最优)

    2.若其不为树,求生成树后额外选一条边即可,即所有节点均被选择

    进一步的,考虑结合第2种情况(指长度为$2m$)的选择——

    同样将首尾相邻的非0元素连边,对于所有选择后者的边,若在同一颗树(指第1种情况中)出现两次显然不优

    换言之,将第1种情况中的树上所有点缩点,问题即求此时的最大匹配

    这张图中有$o(A)$个点和$o(n)$条边(其中$A=\max_{i=1}^{n}a_{i}$),直接使用带花树算法即可

    关于带花树算法,具体即类似匈牙利算法,并当dfs过程中发现奇环时将奇环缩点

    通过调整旋转方向,可以使得新图中的增广路也在原图中存在(反之显然),正确性即得证

    关于实现方式,略微比较复杂,具体如下——

    通常使用bfs代替dfs,并对增广路上(当前)非匹配边中远离起点的点记录另一个点

    当发现奇环时,由于之后还需要得到方案,需要将非匹配边的"另一个点"也记录对应的另一个点(即相互记录)

    设当前搜到的(非匹配边)为$(x,y)$,将两点交替向上爬(类似求lca),至多多爬一次即可得到该环

    另外,对于环上直接通过匹配边拓展的点,其余边也可以拓展,需要重新加入队列

    时间复杂度(我觉得)为$o(|V||E|)$,可以通过

    时间复杂度为$o(An)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 300005
      4 #define M 605
      5 #define fi first
      6 #define se second
      7 struct Edge{
      8     int nex,to,tp;
      9 }edge[N<<1];
     10 pair<int,int>v[N];
     11 queue<int>q;
     12 vector<int>bl[M];
     13 int n,m,n0,V,E,x,y,a[N],id[N],visc[N],vis0[N],head[M],vis[M],pos[M],rt[M],fr[M],fa[M],bj[M],pre[M],match[M];
     14 //visc[i]=1当且仅当第i种颜色被使用(1<=i<M-4)
     15 //vis0[i]=1当且仅当第i段已经被完全确定 
     16 void add(int x,int y,int z){
     17     edge[E]=Edge{head[x],y,z};
     18     head[x]=E++;
     19 }
     20 void dfs1(int k,int fa){
     21     if (pos[k]){
     22         rt[V]=k,fr[V]=fa;
     23         return;
     24     }
     25     pos[k]=V;
     26     for(int i=head[k];i!=-1;i=edge[i].nex)
     27         if (edge[i].tp!=fa)dfs1(edge[i].to,edge[i].tp);
     28 }
     29 void dfs2(int k,int fa){
     30     if (vis[k])return;
     31     vis[k]=1;
     32     if (fa){
     33         vis0[fa]=1;
     34         x=v[fa].fi,y=v[fa].se;
     35         if (a[x-1]==k){
     36             a[x]=k;
     37             for(int i=x+1;i<=y;i+=2)a[i]=a[i+1]=id[n0--];
     38         }
     39         else{
     40             a[y]=k;
     41             for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--];
     42         }
     43     }
     44     for(int i=0;i<bl[k].size();i++){
     45         if (vis0[bl[k][i]])continue;
     46         x=v[bl[k][i]].fi,y=v[bl[k][i]].se;
     47         if ((y-x)&1){
     48             vis0[bl[k][i]]=1;
     49             for(int i=x;i<=y;i+=2)a[i]=a[i+1]=id[n0--];
     50         }
     51     }
     52     for(int i=head[k];i!=-1;i=edge[i].nex)
     53         if (edge[i].tp!=fa)dfs2(edge[i].to,edge[i].tp);
     54 }
     55 int find(int k){
     56     if (k==fa[k])return k;
     57     return fa[k]=find(fa[k]);
     58 }
     59 int lca(int x,int y){
     60     bj[0]++,x=find(x),y=find(y);
     61     while (bj[x]!=bj[0]){
     62         bj[x]=bj[0],x=find(pre[match[x]]);
     63         if (y)swap(x,y);
     64     }
     65     return x;
     66 }
     67 void merge(int k,int lst,int x){
     68     while (find(k)!=x){
     69         pre[k]=lst,lst=match[k];
     70         if (find(k)==k)fa[k]=x;
     71         if (find(lst)==lst)fa[lst]=x;
     72         if (vis[lst]>0){
     73             vis[lst]=0;
     74             q.push(lst);
     75         }
     76         k=pre[lst];
     77     }
     78 }
     79 void bfs(int k){
     80     memset(vis,-1,sizeof(vis));
     81     memset(pre,0,sizeof(pre));
     82     for(int i=1;i<=V;i++)fa[i]=i;
     83     while (!q.empty())q.pop();
     84     vis[k]=0,q.push(k);
     85     while (!q.empty()){
     86         int k=q.front();
     87         q.pop();
     88         for(int i=head[k];i!=-1;i=edge[i].nex){
     89             int x=edge[i].to;
     90             if ((find(k)==find(x))||(vis[x]>0))continue;
     91             if (vis[x]<0){
     92                 vis[x]=1,pre[x]=k;
     93                 if (!match[x]){
     94                     while (x){
     95                         int y=pre[x],xx=match[y];
     96                         match[x]=y,match[y]=x,x=xx;
     97                     }
     98                     return;
     99                 }
    100                 vis[match[x]]=0,q.push(match[x]);
    101                 continue;
    102             }
    103             int z=lca(k,x);
    104             merge(k,x,z),merge(x,k,z); 
    105         }
    106     }
    107 }
    108 void calc1(){
    109     q.push(0);
    110     for(int i=1;i<n;i++)
    111         if ((a[i])&&(a[i]==a[i+1]))q.push(a[i]);
    112     for(int i=1,j=1;i<=n+1;i++)
    113         if ((i>n)||(a[i])){
    114             if (j<i){
    115                 v[++m]=make_pair(j,i-1);
    116                 bl[a[j-1]].push_back(m);
    117                 bl[a[i]].push_back(m);
    118             }
    119             j=i+1;
    120         }
    121     while (!q.empty()){
    122         int k=q.front();
    123         q.pop();
    124         if (k)visc[k]=1;
    125         for(int i=0;i<bl[k].size();i++){
    126             if (vis0[bl[k][i]])continue;
    127             vis0[bl[k][i]]=1;
    128             x=v[bl[k][i]].fi,y=v[bl[k][i]].se;
    129             if ((y-x)&1){
    130                 for(int i=x;i<=y;i+=2)a[i]=a[i+1]=id[n0--];
    131             }
    132             else{
    133                 if (a[x-1]!=k){
    134                     q.push(a[x-1]),a[x]=a[x-1];
    135                     for(int i=x+1;i<=y;i+=2)a[i]=a[i+1]=id[n0--];
    136                 }
    137                 if (a[y+1]!=k){
    138                     q.push(a[y+1]),a[y]=a[y+1];
    139                     for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--];
    140                 }
    141                 if ((a[x-1]==k)&&(a[y+1]==k)){
    142                     a[y]=1;
    143                     for(int i=x;i<y;i+=2)a[i]=a[i+1]=id[n0--];
    144                 }
    145             }
    146         }
    147         bl[k].clear();
    148     }
    149 }
    150 void calc2(){
    151     E=0;
    152     memset(head,-1,sizeof(head));
    153     memset(pos,0,sizeof(pos));
    154     for(int i=1;i<=m;i++)
    155         if (!vis0[i]){
    156             x=v[i].fi,y=v[i].se;
    157             if ((y-x+1)&1){
    158                 add(a[x-1],a[y+1],i);
    159                 add(a[y+1],a[x-1],i);
    160             }
    161         }
    162     for(int i=1;i<M-4;i++)
    163         if ((!visc[i])&&(!pos[i]))V++,dfs1(i,0);
    164     E=0;
    165     memset(head,-1,sizeof(head));
    166     memset(match,0,sizeof(match));
    167     for(int i=1;i<=m;i++)
    168         if (!vis0[i]){
    169             x=v[i].fi,y=v[i].se;
    170             if ((rt[pos[a[x-1]]])||(rt[pos[a[y+1]]]))continue; 
    171             if ((y-x)&1){
    172                 x=pos[a[x-1]],y=pos[a[y+1]];
    173                 if (x!=y)add(x,y,i),add(y,x,i);
    174             }
    175         }
    176     for(int i=1;i<=V;i++)
    177         if (!match[i])bfs(i);
    178     for(int i=1;i<=V;i++)
    179         if ((match[i])&&(i<match[i])){
    180             for(int j=head[i];j!=-1;j=edge[j].nex)
    181                 if (edge[j].to==match[i]){
    182                     vis0[edge[j].tp]=1;
    183                     x=v[edge[j].tp].fi,y=v[edge[j].tp].se;
    184                     a[x]=rt[pos[a[x-1]]]=a[x-1];
    185                     a[y]=rt[pos[a[y+1]]]=a[y+1];
    186                     for(int k=x+1;k<y;k+=2)a[k]=a[k+1]=id[n0--];
    187                     break;
    188                 }
    189         }
    190     E=0;
    191     memset(head,-1,sizeof(head));
    192     memset(vis,0,sizeof(vis));
    193     for(int i=1;i<=m;i++)
    194         if (!vis0[i]){
    195             x=v[i].fi,y=v[i].se;
    196             if ((y-x+1)&1){
    197                 add(a[x-1],a[y+1],i);
    198                 add(a[y+1],a[x-1],i);
    199             }
    200         }
    201     for(int i=1;i<M-4;i++)
    202         if ((!visc[i])&&(!rt[pos[i]]))rt[pos[i]]=i;
    203     for(int i=1;i<=V;i++)dfs2(rt[i],fr[i]);
    204     for(int i=1;i<=m;i++)
    205         if (!vis0[i]){
    206             x=v[i].fi,y=v[i].se;
    207             if ((y-x)&1){
    208                 for(int j=x;j<=y;j+=2)a[j]=a[j+1]=id[n0--];
    209             }
    210             else{
    211                 a[y]=1;
    212                 for(int j=x;j<y;j+=2)a[j]=a[j+1]=id[n0--];
    213             }
    214         }
    215 }
    216 int main(){
    217     scanf("%d",&n);
    218     for(int i=1;i<=n;i++){
    219         scanf("%d",&a[i]);
    220         visc[a[i]]=1;
    221     }
    222     for(int i=1;i<=n;i++)
    223         if (!visc[i])id[++n0]=i;
    224     memset(visc,0,sizeof(visc));
    225     calc1(),calc2();
    226     for(int i=1;i<=n;i++)printf("%d ",a[i]);
    227     return 0;
    228 }
    View Code
  • 相关阅读:
    config 文件夹中的 dev.env.js
    config 文件夹中的 index.js
    Dialog 对话框 可拖拽
    Pagination 分页 封装
    ElasticSearch学习03--使用Java连接ES
    ElasticSearch学习02--使用Kibana管理ES
    ElasticSearch学习01--基本结构与操作
    redis学习02--使用Jedis调用Redis
    redis学习01--常用命令
    Java基础学习08--JDK1.8特性
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15802045.html
Copyright © 2011-2022 走看看