GYM 101173 F.Free Figurines(贪心||并查集)

原题链接

题意
俄罗斯套娃,给出一个初始状态和终止状态,问至少需要多少步操作才能实现状态转化

贪心做法
如果完全拆掉再重装,答案是p[i]和q[i]中不为0的值的个数。现在要求寻找最小步数,显然要减去一些多余的步数。如果初始的一些链的前端是终止的某一条链的连续的一部分,那么这条链就不用被拆开再连上,这样每一个长度为x的链对答案的贡献就是-2*(x-1),对每条链进行同样的操作之后就是答案

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
#define ull unsigned long long
#define LOCAL

using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;

int p[maxn],q[maxn];
int n;
int main(){
    scanf("%d",&n);
    int vis[maxn];
    int ans=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&p[i]);
        if(p[i]) vis[p[i]]=1,ans++;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&q[i]);
        if(q[i]) vis[q[i]]=1,ans++;
    }
    
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            int x=i;
            while(p[x]&&q[x]&&p[x]==q[x]){
                ans-=2;
                x=p[x];
            }
        }
    }
    printf("%d
",ans);
    return 0;
}

并查集

只能进行2个操作:
1、 把一个没有父节点的节点作为一个 没有父节点和子节点的节点的子节点,代价为 1;

2、把一个没有父节点的节点的子节点去掉,代价为1;

那么只能对free的节点进行操作,所以当ai!=bi时,要先把ai拆掉,但必须先满足ai为free才能把i变成free,
同理把i插到bi上时也要满足bi节点为free(即该节点没有父节点)。

#include <iostream>
#include <cstdio>
 
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 8;
 
int a[MAXN], b[MAXN], fa;
 
int main()
{
    #ifdef LOCAL
    freopen("f.txt", "r", stdin);
    //freopen("f.out", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);
 
    int n, i, ans = 0, t;
    cin >> n;
    for(i = 1; i <= n; i++){
        cin >> a[i];
    }
    for(i = 1; i <= n; i++){
        cin >> b[i];
    }
    for(i = 1; i <= n; i++){
        if(a[i] == b[i]) continue;
        if(a[i] != 0){
            ans++;
            fa = a[i];
            a[i] = 0;
            while(a[fa]){
                t = fa;
                fa = a[fa];
                a[t] = 0;
                ans++;
            }
        }
    }
    for(i = 1; i <= n; i++){
        if(a[i] == b[i]) continue;
        if(b[i] != 0){
            fa = a[b[i]];
            if(fa){
                a[b[i]] = 0;
                ans++;
            }
            else{
                continue;
            }
            while(a[fa]){
                t = fa;
                fa = a[fa];
                a[t] = 0;
                ans++;
            }
        }
    }
    for(i = 1; i <= n; i++){
        if(a[i] == b[i]) continue;
        ans++;
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/fht-litost/p/7266399.html