zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 038 F

    洛谷题面传送门 & Atcoder 题面传送门

    好久前做的题了……今天偶然想起来要补个题解

    首先考虑排列 (A_i) 要么等于 (i),要么等于 (P_i) 这个条件有什么用。我们考虑将排列 (P_i) 拆成一个个置换环,那么对于每一个 (i),根据其置换环的情况可以分出以下几类:

    • 如果 (i) 所在置换环大小为 (1),即 (P_i=i),那么 (A_i) 别无选择,只能等于 (i)
    • 如果 (i) 所在置换环大小不为 (1),那么 (A_i) 有两种选择,(A_i=i) 或者 (A_i=P_i)
      • 如果 (A_i=i),那么假设 (j) 为满足 (P_j=i) 的位置,那么由于排列中元素不能重复,因此 (A_j e P_j=i),即 (A_j=j),我们再找出 (P_k=j)(k),也应有 (A_k=k),这样即可确定整个置换环上元素的情况。
      • 如果 (A_i=P_i),类似地,设 (j=P_i),那么 (A_j e j),因为排列中元素不能重复,故 (A_j=P_j),我们再找出 (k=P_j) 的位置 (k),也应有 (A_k=P_k),这样也能够确定整个置换环的 (A)

    也就是说,对于一个置换环而言,我们可以将其视作一个整体看待——这个置换环中要么所有元素的 (A_i) 都等于其本身,要么所有元素的 (A_i) 都等于 (P_i),为了使表述更加具体形象,我们把前一种情况称作“转”(orz wlzhouzhuan),后一种情况称作“不转”。那么对于每一个下标 (i),它是否产生的 (A_i=B_i) 的情况如下:

    • 如果 (i=P_i=Q_i),那么不管怎样都有 (A_i=B_i),我们完全可以直接令答案加一,并忽略这种情况。
    • 如果 (i=P_i e Q_i),那么若 (Q_i) 所在置换环不转就会有 (A_i=B_i=i),对答案产生 (1) 的贡献,若 (Q_i) 所在置换环转则不会产生这样的情况。
    • 如果 (i=Q_i e P_i),同理,若 (P_i) 所在置换环不转则重复元素个数 (+1),否则重复元素个数不变。
    • 如果 (i e P_i=Q_i),那么如果 (P_i) 所在置换环与 (Q_i) 所在置换环同时转/同时不转那么重复元素个数 (+1),否则重复元素个数不变。
    • 如果 (i e P_i e Q_i),那么如果 (P_i) 所在置换环与 (Q_i) 所在置换环同时不转那么重复元素个数 (+1),否则重复元素个数不变。

    如果我们将每个置换环“转”看作被划分入 A 集合,“不转”看作被划分入 B 集合,那么上述条件可以转化为:

    • (i=P_i e Q_i):如果 (Q_i) 所在置换环属于 B 那么答案加 (1)
    • (i=Q_i e P_i):如果 (P_i) 所在置换环属于 B 那么答案加 (1)
    • (i e P_i=Q_i):如果 (P_i,Q_i) 所在置换环属于相同集合那么答案加 (1)
    • (i e P_i e Q_i):如果 (P_i,Q_i) 都属于 B 集合那么答案加 (1)

    看到“划分为两个集合”,“如果两点属于相同/不同集合则代价加 (1),求最小/最大代价”之类的字眼,我们能够想到……最小割!具体来说,我们将每个置换环看作一个点,并新建源汇,我们定义 (P) 中的置换环转当且仅当其与 (S) 相连,不转当且仅当其与 (T) 相连;(Q) 中的置换环转当且仅当其与 (T) 相连,不转当且仅当其与 (S) 相连,这样所有代价都可以用一/两条网络流上的 (1) 权边的形式表述,再根据最大流 (=) 最小割求出最小代价即可。

    时间复杂度同 dinic 求二分图匹配,(mathcal O(nsqrt{n}))

    const int MAXN=1e5;
    const int MAXV=1e5+2;
    const int MAXE=2e5*2;
    const int INF=0x3f3f3f3f;
    int n,a[MAXN+5],b[MAXN+5],S=1e5+1,T=1e5+2,ncnt=0;
    int bel_a[MAXN+5],bel_b[MAXN+5];
    int hd[MAXV+5],to[MAXE+5],cap[MAXE+5],nxt[MAXE+5],ec=1;
    void adde(int u,int v,int f){
    	to[++ec]=v;cap[ec]=f;nxt[ec]=hd[u];hd[u]=ec;
    	to[++ec]=u;cap[ec]=0;nxt[ec]=hd[v];hd[v]=ec;
    } int dep[MAXV+5],now[MAXV+5];
    bool getdep(){
    	memset(dep,-1,sizeof(dep));dep[S]=0;
    	queue<int> q;q.push(S);now[S]=hd[S];
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int e=hd[x];e;e=nxt[e]){
    			int y=to[e],z=cap[e];
    			if(z&&!~dep[y]){
    				dep[y]=dep[x]+1;
    				now[y]=hd[y];q.push(y);
    			}
    		}
    	} return ~dep[T];
    }
    int getflow(int x,int f){
    	if(x==T) return f;int ret=0;
    	for(int &e=now[x];e;e=nxt[e]){
    		int y=to[e],z=cap[e];
    		if(z&&dep[y]==dep[x]+1){
    			int w=getflow(y,min(f-ret,z));
    			ret+=w;cap[e]-=w;cap[e^1]+=w;
    			if(f==ret) return ret;
    		}
    	} return ret;
    }
    int dinic(){
    	int ret=0;
    	while(getdep()) ret+=getflow(S,INF);
    	return ret;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]),++a[i];
    	for(int i=1;i<=n;i++) scanf("%d",&b[i]),++b[i];
    	for(int i=1;i<=n;i++) if(!bel_a[i]){
    		bel_a[i]=(i^a[i])?(++ncnt):ncnt;int cur=a[i];
    		while(cur^i) bel_a[cur]=ncnt,cur=a[cur];
    	}
    	for(int i=1;i<=n;i++) if(!bel_b[i]){
    		bel_b[i]=(i^b[i])?(++ncnt):ncnt;int cur=b[i];
    		while(cur^i) bel_b[cur]=ncnt,cur=b[cur];
    	} int res=n;
    	for(int i=1;i<=n;i++){
    		if(a[i]==i&&b[i]==i) res--;
    		else if(a[i]!=i&&b[i]!=i){
    			if(a[i]==b[i]) adde(bel_a[i],bel_b[i],1),adde(bel_b[i],bel_a[i],1);
    			else adde(bel_b[i],bel_a[i],1);
    		} else {
    			if(a[i]==i) adde(bel_b[i],T,1);
    			else adde(S,bel_a[i],1);
    		}
    	} printf("%d
    ",res-dinic());
    	return 0;
    }
    
  • 相关阅读:
    DL/T 467-2019 电站磨煤机及制粉系统性能试验
    fidlder-05(拦截并修改数据)
    fiddler-04(怎么对APP抓包)
    Redis5设计与源码分析读后感(二)简单动态字符串SDS
    Jedis连接搭建在阿里云服务器上的Redis,基于Linux(CentOS7)
    centos7下安装redis6.0版本+3种启动方式
    Linux下端口被占用的解决方法
    Linux卸载Nginx
    linux中普通用户修改密码出现(passwd:Authentication token manipulation error)
    linux重置密码提示与用户名相似该怎么解决?
  • 原文地址:https://www.cnblogs.com/ET2006/p/agc038F.html
Copyright © 2011-2022 走看看