CF-#Round 84-div2-D题

CF-#Round 84-div2-D题

D. Infinite Path

传送门

这道题比E题难些=-=(虽然我没写,我是看ac人数看的emmm)
今天蓝桥杯的校内模拟赛出来了。
伤心了。。。抑郁了一会会。。13。。。啊啊啊这是什么鬼名次。校内都13。。。
还是题目刷的不够不精。。这样下去能不能进决赛都是问题。。

题目大意:给定了一个序列。以及他们所含有的颜色。
给出了p^k = p * p * p *…*p定义。乘方定义
问使得最小的k使得某无限的序列中颜色一样。

这个题目转换成图论就行。dfs
把图画出来。
就是下标为1的指向数组下标为1的内容的数字。
依次这么转换,这个转换应该还挺简单的。。
因为我都想得到哈哈哈
我们转换为图之后会形成互不干扰的多个环。

p^k转换为在图中走k步。
我们把每个环的结点个数cnt记录下来。
考虑求每个环结点个数cnt的因数。
为啥?
因为我们可以模拟一下。
当i不是cnt的因数时。模拟下来仍然是一个环。就是顺序变了
当i是cnt的因数时。我们可以把当前环分成多个小环了。此时小环的结点个数时cnt / i;我们就判断小环的结点的颜色是否相同。这个地方好判断

所以我们就用dfs()分成多个环。
用judge()判断小环是否满足颜色相同的要求。
维护一下ans最小值就行。

在judge()函数中有一个下标处理:
走x步之后到达结点的颜色。因为我们需要mod cnt嘛。然后如果恰好为cnt的倍数之后,mod求余完是0,但是我们颜色记录是从1开始的。
所以小tips:i = (i + x - 1) % cnt + 1;
这样可以保证可以到达cnt。没有0的情况
嘿嘿。这里卡了一会。

代码部分:

#include <bits/stdc++.h>
#define mst(a, n) memset(a, n, sizeof(a))
using namespace std;
const int N = 2e5 + 10;
const int INF = 1e9 + 10;

int p[N];
int c[N];
int tmp[N];
int vis[N];
int ans;
int cnt;
int n;

int judge(int x, int y)
{
	for (int i = 1; i <= x; i++)
	{
		int t = i;
		int flag = 0;
		for (int j = 1; j <= y; j++)
		{
			if (c[tmp[t]] != c[tmp[i]])
			{
				flag = 1;
				break;
			}
			t = (t + x - 1) % cnt + 1;
		}
		if (!flag)
		{
			return 1;
		}
	}
	return 0;
}

void dfs(int x)
{
	cnt = 0;
	tmp[++cnt] = x;
	vis[x] = 1;
	
	for (int i = p[x]; i != x; i = p[i])
	{
		tmp[++cnt] = i;
		vis[i] = 1;
	}
	for (int i = 1; i * i <= cnt; i++)
	{
		if (!(cnt % i))
		{
			if (judge(i, cnt / i))
			{
				ans = min(ans, i);
				return ;
			}
			if (judge(cnt / i, i))
			{
				ans = min(ans, cnt / i);
			}
		}
	}
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		cin >> n;
		mst(vis, 0);
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &p[i]);
		}
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &c[i]);
		}
		ans = INF;
		for (int i = 1; i <= n; i++)
		{
			if (!vis[i])
			{
				dfs(i);
			}
		}
		cout << ans << endl;
	}
	return 0;
}
发布了111 篇原创文章 · 获赞 3 · 访问量 2613

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/105105141
今日推荐