专题测试四 图论 A - pSort

  1. 题目

    One day n cells of some array decided to play the following game. Initially each cell contains a number which is equal to it's ordinal number (starting from 1). Also each cell determined it's favourite number. On it's move i-th cell can exchange it's value with the value of some other j-th cell, if |i - j| = di, where di is a favourite number of i-th cell. Cells make moves in any order, the number of moves is unlimited.

    The favourite number of each cell will be given to you. You will also be given a permutation of numbers from 1 to n. You are to determine whether the game could move to this state.

    Input

    The first line contains positive integer n (1 ≤ n ≤ 100) — the number of cells in the array. The second line contains n distinct integers from 1 to n — permutation. The last line contains n integers from 1 to n — favourite numbers of the cells.

    Output

    If the given state is reachable in the described game, output YES, otherwise NO.

    Sample 1
    Input Output
    5
    5 4 3 2 1
    1 1 1 1 1
    
    YES
    
    Sample 2
    Input Output
    7
    4 3 5 1 2 7 6
    4 6 6 1 6 6 1
    
    NO
    
    Sample 3
    Input Output
    7
    4 2 5 1 3 7 6
    4 6 6 1 6 6 1
    
    YES
    
  2. 思路
    写之前先吐槽下,这个星期的题都是些什么高达
    元素可以换到自己最喜欢的距离上,意味着这个元素可以与自己距离d的元素任意交换
    对于任意两个元素a和b,如果a能和c交换,b也能和c交换,那么经由c进行中转,a、b也能交换,而且可以不改变c处元素的值
    所以任意两个可以交换的元素可以视为在一个连通块中,在一个连通块中的元素可以任意交换而不产生其他影响
    用并查集判断每个元素当前位置和目标位置在不在一个连通块中,都满足则YES,不满足则NO
  3. 代码
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    
    int fa[105],p[105],love[105];
    
    int find(int x)
    {
    	if(fa[x]!=x)
    		fa[x] = find(fa[x]);
    	return fa[x];
    }
    
    void build(int x,int y)
    {
    	int a=find(x);
    	int b=find(y);
    	fa[a] = b;
    }
    
    int main()
    {
    	int n,q;
    	long long ans;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		fa[i] = i;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&q);
    		p[q]=i;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&love[i]);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(i-love[i]>=1)
    		build(i,i-love[i]);
    		if(i+love[i]<=n)
    		build(i,i+love[i]);
    	}
    	int f=1;
        for(int i=1;i<=n;i++)
        {
    		if(find(p[i])!=find(i))
    		{
    			f=0;
    			break;
    		}
        }
    	if(f==1)
    	{
    		printf("YES\n");
    	}
    	else
    	{
    		printf("NO\n");
    	}
    	return 0;
    }
posted @ 2022-02-21 14:52  Benincasa  阅读(27)  评论(0编辑  收藏  举报