No.100 直列あみだくじ - yukicoder
- 1,...,n の順列(置換)のなかから該当のものを抜き出すという問題。
- 愚直にやると n! だが置換が巡回置換の積であるということを用いれば、各巡回置換(下のコードでは group)を独立して確定してやればよいので O(N^3)
- group 構築時に自己ループ判定が抜けてバグった。
- dfs で書くと、無駄に save_xx 変数を用意しないで済むみたいだし、 used フラグは N <= 60 なんで int64 にもたせると bit 演算でフラグ管理ができるっぽい。(参考 yukicoder : No.100 直列あみだくじ - kmjp's blog)
class SeriesAmidakuji {
public:
bool make_group(vector<int> &s, int start, vector<bool> &used, const vector<int> &A) {
vector<int> save_s = s;
vector<bool> save_u = used;
int cur = start;
do {
if (s[cur] == A[cur])
return false;
s[s[cur]] = A[cur];
cur = s[cur];
} while (cur != start);
cur = start;
do {
used[cur] = true;
if (s[s[cur]] != A[cur])
{
s = save_s;
used = save_u;
return false;
}
cur = s[cur];
} while (cur != start);
return true;
}
void solve(void) {
int N;
cin>>N;
vector<int> A(N);
REP(i,N)
{
cin>>A[i];
--A[i];
}
vector<int> s(N,-1);
vector<bool> used(N,false);
REP(i,N)
{
if (i == A[i])
{
s[i] = i;
used[i] = true;
}
}
REP(i,N)
{
if (s[i] >= 0)
continue;
REP(j,N)
{
if (i==j)
continue;
if (used[j])
continue;
s[i] = j;
if (make_group(s,i,used,A))
break;
s[i] = -1;
}
if (s[i] < 0)
{
cout<<"No"<<endl;
return;
}
}
cout<<"Yes"<<endl;
}
};