Jzoj P4221 互相追逐的点___dfs+环

版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/86681674

题目大意:

平面上有 n n 个点,初始任意两个点距离 > = 1 >=1 ,点 i ( i [ 1 , n ] ) i(i∈[1,n]) 有一个值 a [ i ] a[i]
所有点同时开始移动,点 i ( i [ 1 , n ] ) i(i∈[1,n]) 的运动速率为 1 1 单位/秒,方向为它到点 a [ i ] a[i] 连线方
向(点 i i 与点 a [ i ] a[i] 重合的话点 i i 此刻将不会移动)。
如果某时刻点 i i 与点 a [ i ] a[i] 距离为 1 1 或这个时刻之前的 1 1 秒内点 i i 与点 a [ i ] a[i] 距离保持不变,则自该时刻起点 i i 的运动方向将变为恒与点 a [ i ] a[i] 相同。
如果点 i i 的运动方向不是它到点 a [ i ] a[i] 连线方向而是恒与点 i i 本身相同(取决于点 i i 本身),则称点 i i “不知道向哪里移动”。求经过无限长的时间后的任意一组运动方向相同的“不知道向哪里移动”的点。另外如果一个点“不知道向哪里移动”,它将不动。
1 < = N < = 200000 1 < = a i < = N 1 0 9 < = x i , y i < = 1 0 9 1<=N<=200000,1<=ai<=N,-10^9<=xi,yi<=10^9

分析:

真实题目实在是,实在是,,,太exin(疯狂吐槽)
注意到一个点 i i “不知道向哪里移动”当且仅当 a [ a [ a [ . . . a [ i ] . . . ] ] ] = i a[a[a[...a[i]...]]]=i 。此时点 i i
所属的一组“不知道向哪里移动”的点为 a [ i ] , a [ a [ i ] ] , a [ a [ a [ i ] ] ] , . . . . . . , i a[i], a[a[i]], a[a[a[i]]], ......, i 。所以可以
枚举点 i i ,看 a [ i ] , a [ a [ i ] ] , . . . . . . a[i], a[a[i]], ...... 是否 = i =i ,如果一直到 a [ a [ . . . a [ n a [ i ] . . . ] ] ] a[a[...a[(共 n 个“a[”)i]...]]]
都不等于 i i 或一直到 a [ a [ . . . a [ k a [ i ] . . . ] ] ] a[a[...a[(共 k 个“a[”)i]...]]] 都不等于 i i a [ a [ . . . a [ k a [ i ] . . . ] ] ] = a [ a [ . . . a [ m a [ i ] . . . ] ] ] k > = m a[a[...a[(共 k 个“a[”)i]...]]]=a[a[...a[(共 m 个“a[”)i]...]]](k>=m) ,那么点 i i 不可能“不知道向哪里移动”。找到第一个“不知道向哪里移动”的点后即可输出该点所。.
在此基础上,如果找到 a [ a [ . . . a [ k a [ i ] . . . ] ] ] = a [ a [ . . . a [ m a [ i ] . . . ] ] ] k > = m a[a[...a[(共 k 个“a[”)i]...]]]=a[a[...a[(共 m个“a[”)i]...]]](k>=m) ,则 a [ a [ . . . a [ m a [ i ] . . . ] ] ] a[a[...a[(共 m 个“a[”)i]...]]] “不知道向哪里移动”。根据抽屉原理, i , a [ i ] , . . . . . . , a [ a [ . . . a [ n a [ i ] . . . ] ] ] i, a[i], ......, a[a[...a[(共 n 个“a[”)i]...]]] 中必有两个数相等,所以任取点 i i 即可找到一个“不知道向哪里移动”的点。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <algorithm>

#define N 200005

using namespace std;

int lovenum[N], first[N], huan[N], cnt, n;
bool vis[N];
 
int main()
{	
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &lovenum[i]);
    int x, y;
    for (int i = 1; i <= n; i++) scanf("%d%d",&x, &y);
    int Number = 1;
    while (!vis[Number])
    {	
        vis[Number] = 1;
        huan[++cnt] = Number;
        first[Number] = cnt;
        Number = lovenum[Number];
        if (vis[Number])
        {
		    printf("%d\n", cnt - first[Number] + 1);
		    for (int i = first[Number]; i <= cnt; i++) printf("%d ", huan[i]); printf("\n");
		} 
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Gx_Man_VIP/article/details/86681674