1327D Infinite Path(圖論+思維)

1327D Infinite Path(圖論+思維)

題面

題意:有 TT 個詢問,每個詢問有長度爲 nn 的被染色排列 p1pnp_1\sim p_n,第 ii 位被染色爲 cic_i,排列中每位數字都處於循環 i,p[i],p[p[i]]...i, p[i], p[p[i]]... 中,若該循環中每個數字的顏色都相同則認爲該循環爲有效的。現在有一個操作,讓該排列每個數字 p[i]p[i] 變成 p[p[i]]p[p[i]]。現在問至少需要多少次操作纔會出現有效的循環。

範圍1T1e4 , 1n2e5 , 1pin , 1cin1 \le T \le 1e4~,~1 \le n \le 2e5~,~1 \le p_i \le n~,~1 \le c_i \le n

分析:根據題意序列中每個數字都處於環中,只有當環中的所有點顏色相同才爲有效,進行一次操作後構造出新的圖中可能會形成更小的環,我們需要求多少次操作後纔會出現所有點顏色相同的環。可以發現當進行操作的次數 kk 爲環長 ll 的因數時纔會形成更小的環,因此我們可以先預處理出所有的環,對每個環枚舉其所有因數,驗證是否出現有效的環。時間複雜度大約爲 O(nn)O(n\sqrt{n})​

Code

#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;

const int MAXN = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

int n;

inline int read()
{
	int s = 0, w = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')
			w = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
		s = s * 10 + ch - '0', ch = getchar();
	return s * w;
}

int p[MAXN], c[MAXN], vis[MAXN];

signed main()
{
	int T = read();
	while (T--)
	{
		n = read();
		for (int i = 0; i <= n; i++)
			vis[i] = 0;
		for (int i = 1; i <= n; i++)
		{
			p[i] = read();
		}
		for (int i = 1; i <= n; i++)
		{
			c[i] = read();
		}
		int ans = INF;
		for (int i = 1; i <= n; i++)
		{
            // 已經位於環中的點不必再處理
			if (vis[i])
				continue;
            // cycle保存該環中的所有點
			vector<int> cycle;
			int now = i;
			while (cycle.empty() || now != i)
			{
				cycle.push_back(now);
				vis[now] = 1;
				now = p[now];
			}
			int sz = cycle.size();
            // 枚舉所有長度
			for (int step = 1; step <= sz; step++)
			{
                // 必須要是因數纔有意義
				if (sz % step)
					continue;
                // 此時以環中第j個元素作爲起點進行檢查
				for (int j = 0; j < step; j++)
				{
					int color = c[cycle[j]];
					int flag = 0;
					for (int k = j; k < sz; k += step)
					{
                        // 如果新環中點顏色不同則不滿足條件
						if (c[cycle[k]] != color)
						{
							flag = 1;
							break;
						}
					}
                    // 新環中所有點顏色相同則更新答案
					if (!flag)
					{
						ans = min(ans, step);
						break;
					}
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

【END】感謝觀看

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章