https://www.acmicpc.net/problem/9521
처음 이 문제를 접하고, 생각보다 쉽게 해결될 수 있다고 생각했는데 왜 정답률이 22프로인지를 알 수 있던 문제다.
사이클 개념과 DP문제가 혼합되어 있어서 더욱 어렵게 느껴졌다.
먼저 문제를 해결하는 방식은 다음과 같다.
1) 사이클에 N개의 정점이 존재 할 때 N개의 정점을 색칠할 수 있는 경우의 수를 구한다.
2) 사이클에 포함되지 않는 정점들을 모두 K-1씩 곱해준다.
기존 사이클의 개수를 구하는 방식은 DFS 문제의 9486번(텀프로젝트)에 개시했다.
여기서 중요한 점은 사이클이 N개가 존재할 때
1번째 정점과 N-2번째 정점이 같은색인 경우와 다른 색인 경우 2가지가 존재한다.
예를 들어 1->2->3->4->1 과 같은 사이클이 있을 때
4개의 정점을 색칠하는 경우의 수를 구하려면 1번과 3번이 같은 색일 때와 다른 색일 때를 더해줘야 한다는 것이다.
즉, 점화식은 다음과 같다.
color[i] = color[i-2] * (K-1) + color[i-1] * (K-2)
(사이클에서 i개의 정점이 있을 때, 1번째 정점과 i-2번째 정점 색 같을 때 + 1번째 정점과 i-2번째 정점 색 다를 때)
사이클의 개수에 따라서 경우의 수를 모두 곱해주면 되며
전체 정점에서 사이클의 개수를 뺀 모든 정점은 다른 정점과 연결이 되어있기 때문에
연결된 정점과 다른 K-1가지 색을 계속해서 곱해주면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include <iostream> using namespace std; #define inf 1000000007; long ans=1; int N; long K; int start_point=0; //사이클 방문 시 시작 정점 long color[1000001]={0}; //사이클 개수 별 경우의 수 int first_visit[1000001]={0}; //사이클 방문 시 노드 별 시작 정점 int visited[1000001]={0}; //사이클 방문 시 방문 순번 int f[1000001]={0}; int dfs(int current,int cnt){ if(visited[current]){ //기존 사이클과 다른 정점 방문 시 (사이클 x) if(first_visit[current]!=start_point) return 0; return cnt-visited[current]; } visited[current]=cnt; first_visit[current]=start_point; return dfs(f[current],cnt+1); } int main(){ cin>>N>>K; for(int i=1;i<=N;i++){ scanf("%d",&f[i]); } color[0]=1; color[1]=K; color[2]=(K*(K-1))%inf; color[3]=(K*(K-1)*(K-2))%inf; for(int i=4;i<=N;i++){ //1번째와 i-2가 같은색일 때 + 1번째와 i-2가 다른색일 때 color[i]=color[i-2]*(K-1)+color[i-1]*(K-2); color[i]%=inf; } int single_cnt=N; //사이클이 아닌 정점 개수 int cycle_cnt=0; //사이클에 포함되는 정점 개수 for(int i=1;i<=N;i++){ if(!visited[i]){ start_point=i; cycle_cnt=dfs(i,1); ans*=color[cycle_cnt]; ans%=inf; single_cnt-=cycle_cnt; } } for(int i=1;i<=single_cnt;i++){ ans*=(K-1); ans%=inf; } cout<<ans<<endl; return 0; } | cs |
'알고리즘(BOJ) > DFS' 카테고리의 다른 글
백준 3184번 - 양 (0) | 2019.08.08 |
---|---|
백준 16198번 - 에너지 모으기 (0) | 2019.07.18 |
백준 17136번 - 색종이 붙이기 (0) | 2019.04.14 |
백준 14502번 - 연구소 (0) | 2019.03.30 |
백준 2668번 - 숫자 고르기 (3) | 2019.03.29 |