zoukankan      html  css  js  c++  java
  • [cf1491G]Switch and Flip

    将其连有向边$(i,c_{i})$,由于每一个点出入度都为1,那么必然构成若干个环

    对于每一个环,从一点出发,将搜到的点依次记录下来(直至返回自己),记作$v_{1},v_{2},...,v_{k}$,那么就有$c_{v_{i}}=v_{i+1}$(特别的,$c_{v_{k}}=v_{1}$)

    显然可以将其看作一个${1,2,...,k}$到${v_{1},v_{2},...,v_{k}}$的映射,即可以简化为${2,3,...,n,1}$如何解决,有一个$n+1$次的做法,具体操作过程如下:$(2,n)$,$(3,n)$,...,$(n-1,n)$,$(1,n)$,$(1,2)$,$(2,n)$

    (特别的,当$n=2$,再找一个无关的数,参考样例中做法即可,也是3次)

    如果每一个环都需要加1,那么最终次数就是$n+环数 $,显然次数过多

    对于两个大小分别为$x$和$y$的环,类似上面将其描述为${2,3,...,x,1,x+2,...,x+y,x+1}$,我们可以用$x+y$次将其解决,具体操作过程如下:$(x,x+y)$,$(1,x+y)$,$(2,x+y)$,...,$(x-1,x+y)$,$(x+1,x)$,$(x+2,x)$...,$(x+y-1,x)$,$(x,x+y)$

    由此,将两个环配对,最终至多剩下一个环,再用前面的方式即可,至多$n+1$次

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define mp make_pair
     5 vector<int>v[N];
     6 vector<pair<int,int> >ans;
     7 int n,m,a[N],vis[N];
     8 void dfs(int k){
     9     if (vis[k])return;
    10     v[m].push_back(k);
    11     vis[k]=1;
    12     dfs(a[k]);
    13 }
    14 int main(){
    15     scanf("%d",&n);
    16     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    17     for(int i=1;i<=n;i++)
    18         if (!vis[i]){
    19             m++;
    20             dfs(i);
    21             if (v[m].size()==1)v[m--].clear();
    22         }
    23     for(int i=1;i<m;i+=2){
    24         int x=v[i].size(),y=v[i+1].size();
    25         ans.push_back(mp(v[i][x-1],v[i+1][y-1]));
    26         for(int j=0;j+1<x;j++)ans.push_back(mp(v[i][j],v[i+1][y-1]));
    27         for(int j=0;j+1<y;j++)ans.push_back(mp(v[i+1][j],v[i][x-1]));
    28         ans.push_back(make_pair(v[i].back(),v[i+1].back()));
    29     }
    30     if (m&1){
    31         if (v[m].size()==2){
    32             int x=1;
    33             if (v[m][0]==1){
    34                 if (v[m][1]>2)x=2;
    35                 else x=3;
    36             }
    37             ans.push_back(mp(v[m][0],x));
    38             ans.push_back(mp(x,v[m][1]));
    39             ans.push_back(mp(x,v[m][0]));
    40         }
    41         else{
    42             int x=v[m].size();
    43             for(int i=1;i+1<x;i++)ans.push_back(mp(v[m][i],v[m][x-1]));
    44             ans.push_back(mp(v[m][0],v[m][x-1]));
    45             ans.push_back(mp(v[m][0],v[m][1]));
    46             ans.push_back(mp(v[m][1],v[m][x-1]));
    47         }
    48     }
    49     printf("%d
    ",ans.size());
    50     for(int i=0;i<ans.size();i++)printf("%d %d
    ",ans[i].first,ans[i].second);
    51     for(int i=0;i<ans.size();i++){
    52         int x=ans[i].first,y=ans[i].second;
    53         swap(a[x],a[y]);
    54         a[x]*=-1,a[y]*=-1;
    55     }
    56     for(int i=1;i<=n;i++)assert(a[i]==i);
    57 } 
    View Code
  • 相关阅读:
    Prony算法
    基于WeifenLuo.WinFormsUI.Docking界面布局控件的Winform框架
    C# 在父容器中显示子窗体
    如何识别高级的验证码
    我 .北漂的 80后男孩
    c# 主机和网络字节序的转换
    电网割集能量算法
    项目管理心得:一个项目经理的个人体会、经验总结
    Qt 登陆界面实现
    [ lucene FAQ ] 如何避免lucene queryparser中文分词的缺陷?[转]
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14471320.html
Copyright © 2011-2022 走看看