1327D Infinite Path(圖論+思維)
題意:有 個詢問,每個詢問有長度爲 的被染色排列 ,第 位被染色爲 ,排列中每位數字都處於循環 中,若該循環中每個數字的顏色都相同則認爲該循環爲有效的。現在有一個操作,讓該排列每個數字 變成 。現在問至少需要多少次操作纔會出現有效的循環。
範圍:
分析:根據題意序列中每個數字都處於環中,只有當環中的所有點顏色相同才爲有效,進行一次操作後構造出新的圖中可能會形成更小的環,我們需要求多少次操作後纔會出現所有點顏色相同的環。可以發現當進行操作的次數 爲環長 的因數時纔會形成更小的環,因此我們可以先預處理出所有的環,對每個環枚舉其所有因數,驗證是否出現有效的環。時間複雜度大約爲 。
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】感謝觀看