题解:CF1385G Columns Swaps

· · 题解

CF1385G Columns Swaps

思路

手玩一下样例,发现若按照数字类型连边,从上或下其中一个数字连入,另一个数字连出,会形成一个环状结构。
关于自环:换不换都一样,要使得交换次数最小显然不换。
先考虑单个环怎么做:若有一对数字都在上或者下,则选择其中一个上下交换,然后依次扩展到整个环。
显然会有两种方案,另一种就是把这一种中交换的位置不交换,不交换的位置交换。
所以先把每一个环单独找出来,然后计算出两种方案所需的交换次数,取其中较小的一种并加入输出标记,最后输出最小次数和以及交换位置即可。
环之间,由于没有相同数字,所以两种方案可以任意组合,不会相互影响。
这里给出一组由两个环组成的 hack 数据:

input:
3
7
1 1 4 5 2 7 3
2 3 6 6 4 5 7
4
2 1 3 2
1 3 4 4
11
1 1 4 5 2 7 3 9 8 10 9
2 3 6 6 4 5 7 8 10 11 11

output:
3
1 3 5
1
4
4
1 3 5 11

第三组是把第二组按照相对顺序接在第一组后面。

代码

#include<bits/stdc++.h>
#define fir first
#define sec second
#define int long long
#define pii pair<int,int>
#define double long double
#define tomin(a,b) a=min(a,b)
#define tomax(a,b) a=max(a,b)
#define fep(i,s,e) for(int i=s;i<e;i++)
#define pef(i,s,e) for(int i=s;i>e;i--)
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define per(i,s,e) for(int i=s;i>=e;i--)
namespace FastIO{
    template<typename T>inline void read(T &x){
        x=0;int f=1;char c=getchar();
        for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
        for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);x*=f;
    }
    inline void read(char &c){
        c=getchar();
        while(isspace(c))c=getchar();
    }
    inline void read(std::string &s){
        s.clear();char c=getchar();
        for(;isspace(c);c=getchar());
        for(;!isspace(c)&&c!=EOF;c=getchar())s+=c;
    }
    template<typename T,typename...Args>
    void read(T &x,Args&...args){
        read(x);read(args...);
    }
    template<typename T>void print(T x){
        if(x<0)x=-x,putchar('-');
        if(x>9)print(x/10);
        putchar((x%10)^48);
    }
    inline void print(char c){
        putchar(c);
    }
    inline void print(std::string s){
        fep(i,0,s.size())putchar(s[i]);
    }
    inline void print(const char*s){
        while(*s)putchar(*s++);
    }
    template<typename T,typename...Args>
    void print(const T &x,const Args&...args){
        print(x);print(args...);
    }
}
using namespace std;
using namespace FastIO;
const int N=2e5+47;
int T,n,a[N],b[N],cnt[N];
int A[N],B[N],ans,bel[N];
pii l[N],r[N];
vector<int>res;
vector<vector<int>>grp;
void find(int x,int tim){
    grp.push_back({});
    queue<int>q;
    q.push(x);
    while(q.size()){
        int u=q.front();q.pop();
        if(bel[u])continue;bel[u]=tim;
        int a1=l[a[u]].fir,a2=r[a[u]].fir;
        int b1=l[b[u]].fir,b2=r[b[u]].fir;
        if(!bel[a1])q.push(a1);
        if(!bel[a2])q.push(a2);
        if(!bel[b1])q.push(b1);
        if(!bel[b2])q.push(b2);
    }
}
void solve(int k){
    int ans1=0,ans2=0;
    rep(I,0,grp[k].size()-1){
        int i=grp[k][I];
        int L=l[a[i]].fir;
        int R=r[a[i]].fir;
        if(l[a[i]].sec!=r[a[i]].sec)continue;
        int nxt=a[i],cur=a[i];
        while(l[nxt].sec==r[nxt].sec){
            L=l[nxt].fir;
            R=r[nxt].fir;
            swap(A[R],B[R]);cur=nxt;
            nxt=A[R]+B[R]-cur;
            if(R==r[nxt].fir)swap(l[nxt],r[nxt]);
            swap(l[nxt].sec,r[cur].sec);
        }
    }
    rep(I,0,grp[k].size()-1){
        int i=grp[k][I];
        if(A[i]!=a[i])ans1++;
        if(B[i]!=a[i])ans2++;
    }
    ans+=min(ans1,ans2);
    if(ans1<=ans2){
        rep(I,0,grp[k].size()-1){
            int i=grp[k][I];
            if(A[i]!=a[i]){
                res.push_back(i);
            }
        }
    }
    else{
        rep(I,0,grp[k].size()-1){
            int i=grp[k][I];
            if(B[i]!=a[i]){
                res.push_back(i);
            }
        }
    }
}
signed main(){
    read(T);
    while(T--){
        read(n);
        rep(i,1,n)read(a[i]);
        rep(i,1,n)read(b[i]);
        ans=0;
        grp.clear();
        res.clear();
        rep(i,1,n){
            cnt[i]=bel[i]=0;
            l[i]=r[i]={0,0};
            A[i]=a[i],B[i]=b[i];
        }
        rep(i,1,n){
            cnt[a[i]]++;
            cnt[b[i]]++;
            if(l[a[i]].fir==0)l[a[i]]={i,0};
            else r[a[i]]={i,0};
            if(l[b[i]].fir==0)l[b[i]]={i,1};
            else r[b[i]]={i,1};
        }
        int flg=0;
        rep(i,1,n)if(cnt[i]!=2){
            flg=1;break;
        }
        if(flg){
            puts("-1");
            continue;
        }
        int tim=0;
        grp.push_back({});
        rep(i,1,n){
            if(!bel[i]){
                tim++;
                find(i,tim);
            }
        }
        rep(i,1,n){
            grp[bel[i]].push_back(i);
        }
        fep(i,1,grp.size())solve(i);
        print(ans,'\n');
        fep(i,0,res.size()){
            print(res[i],' ');
        }
        print('\n');
    }
}