【AGC038F】Two Permutations

【AGC038F】Two Permutations

by AmanoKumiko

Description

给定两个\(0\ -\ N-1\)的排列\(p,q\)

构造排列\(a,b\),且\(a_i=i\)\(p_i\)\(b\)同理

求出\(max(\sum[a_i\not=b_i])\)

Input

第一行一个整数\(N\),表示排列长度

第二行\(N\)个整数,\(p_0 ... p_{N-1}\)

第三行\(N\)个整数,\(q_0 ... q_{N-1}\)

Output

一行一个整数表示答案

Sample Input

5
1 3 2 0 4
3 0 2 1 4

Sample Output

3

Data Constraint

\(1\le N\le 10^5\)

Solution

你考虑这样一件事,就是说:把排列看成置换

那么一个排列,要么全部保留,要么全部换成对应的\(i\)

你考虑这样一件事,就是说:建出一个网络流模型

我们规定,\(P\)划分到\(S\)为保留,\(Q\)划分到\(T\)为保留

同时,我们考虑最小化\(a_i=b_i\)的个数

\(1.P\not =Q\),不用连边,直接加上贡献

\(2.P\not =i,Q=i\),那么\(a_i=b_i\)当且仅当\(P\)不保留,\(Q\)保留,即\(S\)\(P\)连边,边权为\(1\)

\(3.P=i,Q\not =i\),那么\(a_i=b_i\)当且仅当\(P\)保留,\(Q\)不保留,即\(Q\)\(T\)连边,边权为\(1\)

\(4.P\not =i,Q\not=i,P\not =Q\),那么\(a_i=b_i\)当且仅当\(P,Q\)均不保留,即\(Q\)\(P\)连边,边权为\(1\)

\(5.P\not=i,Q\not=i,P=Q\),那么\(a_i=b_i\)当且仅当\(P,Q\)均保留或均不保留,即\(P\)\(Q\)连,\(Q\)\(P\)连,边权都为\(1\)

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 200010
#define inf 2147483647

int na[N],nb[N],ta,tb,n,a[N],b[N],vis[N],ans,S,T;
int gap[N],dis[N],cur[N],last[N],tot=1;
struct node{int en,v,next;}e[N*10];

void add(int x,int y,int z){e[++tot]=(node){y,z,last[x]};last[x]=tot;}

int dfs(int x,int flow){
	if(x==T)return flow;
	int have=0;
	for(int i=cur[x];i;i=e[i].next){
		cur[x]=i;
		int y=e[i].en;
		if(dis[x]!=dis[y]+1||!e[i].v)continue;
		int now=dfs(y,min(flow-have,e[i].v));
		e[i].v-=now;
		e[i^1].v+=now;
		have+=now;
		if(have==flow)return have;
	}
	cur[x]=last[x];
	if(!(--gap[dis[x]]))dis[0]=T+1;
	++gap[++dis[x]];
	return have;
}

int main(){
	scanf("%d",&n);
	F(i,1,n)scanf("%d",&a[i]),a[i]++;
	F(i,1,n)scanf("%d",&b[i]),b[i]++;
	F(i,1,n){
		ta++;
		for(int now=a[i];!vis[now];now=a[now]){
			na[now]=ta;vis[now]=1;
		}
	}
	memset(vis,0,sizeof(vis));
	F(i,1,n){
		tb++;
		for(int now=b[i];!vis[now];now=b[now]){
			nb[now]=tb;vis[now]=1;
		}
	}
	S=0;T=ta+tb+1;
	F(i,1,n){
		if(a[i]==i&&b[i]==i)ans++;
		if(a[i]==i&&b[i]!=i)add(nb[i]+ta,T,1),add(T,nb[i]+ta,0);
		if(a[i]!=i&&b[i]==i)add(S,na[i],1),add(na[i],S,0);
		if(a[i]!=i&&b[i]!=i){
			if(a[i]==b[i])add(nb[i]+ta,na[i],1),add(na[i],nb[i]+ta,0),add(na[i],nb[i]+ta,1),add(nb[i]+ta,na[i],0);
			else add(nb[i]+ta,na[i],1),add(na[i],nb[i]+ta,0);
		}
	}
	gap[0]=T+1;
	while(dis[S]<T+1)ans+=dfs(S,inf);
	printf("%d",n-ans);
	return 0;
}
posted @ 2021-11-17 21:27  冰雾  阅读(35)  评论(0编辑  收藏  举报