其他分享
首页 > 其他分享> > 2200+专项:F. Nauuo and Portals(构造 并查集)

2200+专项:F. Nauuo and Portals(构造 并查集)

作者:互联网

原题: http://codeforces.com/contest/1173/problem/F

题意:

nnn*nn∗n网格(1,1)(n,n)(1,1)-(n,n)(1,1)−(n,n),n个人从左往右(i,0)(i,0)(i,0),n个人从上往下(0,i)(0,i)(0,i),你可以放多对传送门,来改变这些人的运动轨迹。

要满足左边第iii个人走到(ai,n+1)(a_i,n+1)(ai​,n+1),右边第iii个人走到(n+1,bi)(n+1,b_i)(n+1,bi​),其中aia_iai​不会重复,bib_ibi​也是。

解析:

5
3 1 5 4 2
4 2 1 3 5

一个一个来,以上面的案例为例。左边第二个人要走到第一行,就放一个(2,1)(2,1)(2,1),上面第三个人走到第一列,放(1,3)(1,3)(1,3)。
在这里插入图片描述
接下来是左边5走到2,上面2走到2。

为了满足上面的两个,我们在第一行和第一列不会放了。所以从第二行和第二列开始。
在这里插入图片描述
此时发现,你需要维护一个并查集,表示由之前的传送门的影响,还没有满足的点的动向。
在这里插入图片描述
代码:

#include<bits/stdc++.h>
using namespace std;
#define pill pair<int,int>
const int maxn=1009;
int a[maxn],b[maxn];
int pos[2][maxn];

vector<pill>V;
int fin(int id,int a){
    return pos[id][a]==a?a:pos[id][pos[id][a]]=fin(id,pos[id][a]);
}
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)pos[0][i]=pos[1][i]=i;
    for(int i=1,j;i<=n;i++)scanf("%d",&j),a[j]=i;
    for(int i=1,j;i<=n;i++)scanf("%d",&j),b[j]=i;
    for(int i=1;i<=n;i++){
        int h=fin(0,a[i]),c=fin(1,b[i]);
        if(h==i&&c==i){
            continue;
        }
        V.push_back({h,i}),V.push_back({i,c});
        pos[0][i]=h;
        pos[1][i]=c;
    }
    printf("%d\n",(int)V.size()/2);
    for(int i=0;i<V.size();i+=2){
        printf("%d %d %d %d\n",V[i].first,V[i].second,V[i+1].first,V[i+1].second);
    }
}

标签:2200,Portals,nn,int,查集,pos,传送门,maxn,id
来源: https://blog.csdn.net/jk_chen_acmer/article/details/91403448