문제 링크

  • 나의 풀이

DFS로 이동하며 발자취를 남겨(vector에 push_back)

흔적을 만날때 까지 반복하다가 흔적이 있는 지점을 만나면

시작한 지점부터 탐색을 다시탐색하며 꼬리 지점이 가리킨 지점까지 찾아간다.

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int s[100001], chks[100001];
int T, n;

int solve()
{
    int ret = 0;
    int team_num = 0;
    memset(chks, 0, sizeof(chks));
    for (int i = 1; i <= n; i++)
    {
        if (chks[i])
            continue;
        int idx = i;
        team_num += 1;
        chks[i] = team_num;
        vector<int> team;
        team.push_back(i);
        while (true)
        {
            int tg = s[team.back()];

            if (chks[tg])
            {
                if (chks[tg] == team_num)
                {
                    for (int tm : team)
                    {
                        if (tg == tm)
                            break;
                        ret += 1;
                    }
                }
                else
                    ret += team.size();
                break;
            }
            else
            {
                chks[tg] = team_num;
                team.push_back(tg);
            }
        }
    }
    return ret;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> T;

    while (T--)
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> s[i];

        cout << solve() << "\n";
    }
}
  • 개선된 풀이

vector를 사용하지 않고 풀 수 있다.

#include <cstdio>

char buf[1<<17];

inline char read()
{
    static int idx = 1<<17;
    if (idx == 1<<17)
    {
        fread(buf, 1, 1<<17, stdin);
        idx = 0;
    }
    return buf[idx++];
}
inline int readInt()
{
    int sum = 0;
    char now = read();
    
    while (now == 10 || now == 32) now = read();
    while (now >= 48 && now <= 57)
    {
        sum = sum*10 + now-48;
        now = read();
    }
    
    return sum;
}
int main()
{
    int t = readInt();
    
    while (t--)
    {
        int n = readInt();
        
        int L[n+1];
        for (int i = 1; i <= n; ++i) L[i] = readInt();
        
        bool visited[n+1]{};
        int ans = 0;
        for (int i = 1; i <= n; ++i)
        {
            if (visited[i]) continue;
            
            int v = i;
            while (!visited[v])
            {
                visited[v] = 1;
                v = L[v];
            }
            
            int w = i;
            while (w != v)
            {
                ans++;
                w = L[w];
            }
        }
        
        printf("%d\n", ans);
    }
    
    return 0;
}

댓글남기기