티스토리 뷰
[Codeforces 1093D] Beautiful graph
그래프 문제를 풀 때는 항상 Disjoint된 상태를 고려해야한다는 교훈을 일깨워준 문제.
그래프의 vertex에 1,2,3중에 하나의 숫자를 부여해야 하는데, edge로 연결된 두 vertex끼리는 두 수의 합이 반드시 홀수가 되게 만들어야 한다. 이 조건을 만족하게 숫자를 부여하는 방법의 경우의 수를 구하는 문제이다.
내가 우선 생각한 것은 두 수를 더해서 홀수가 되도록 만드는 방법이었다. 두 수를 더해서 홀수가 되게 하려면 (짝수+홀수) 의 방법밖에 존재하지 않는다. 이 문제에서 사용할 수 있는 짝수는 2밖에 없고, 홀수는 1,3밖에 없다. 그래서 나는 그래프를 구성한 뒤 dfs를 돌면서 각 노드마다 번갈아가면서 홀->짝->홀->짝... 이렇게 부여해주었다. 그런데 문제의 예시데이터 2번처럼 중간에 홀짝이 꼬일 수도 있다. 그 경우는 밑에 소스코드상에서 21~23번 째 줄로 처리하였다. 이런 경우에는 0을 출력하면 된다. 만약 꼬이지 않고 그래프의 모든 노드가 유효하다면, 나는 그 다음에 내가 부여한 홀수의 짝수의 개수를 카운트했다. 그래서 홀수의 개수만큼 2의 거듭제곱을 취해서 답에 더하고(짝수는 어차피 '2' 하나만 존재하므로 경우의 수에 영향을 미치지 않는다), 짝수와 홀수를 서로 바꾼 경우도 있을 수 있으므로 다시 짝수의 개수만큼 2의 거듭제곱을 더했다. 이에 대한 구현이 67번 째 줄에 나와있다. 처음에 이렇게 해서 제출했더니 Wrong Answer를 받았다. 무엇이 문제인가를 봤더니 바로 그래프끼리 disjoint된 상태를 고려하지 않은 것이었다. 예를 들어 V=2,E=0인 데이터가 있다고 생각해보자. 이 상태는 서로 독립된 1번 노드와 2번 노드가 존재하는 상황이다. 각 노드에서 가능한 케이스는 3가지 이므로 3*3=9가지가 답이 되어야 한다. 그런데 내 코드는 모든 노드가 서로 연결되어있다고 가정해서 even=2, odd=0이라고 카운트한 것이다. 이러면 답이 5가 나오기 때문에 틀린 것이다. 이를 해결하기 위해선 disjoint관계에 있는 그래프끼리는 서로 경우의 수를 곱해주어야 한다. 그래프 문제는 항상 disjoint 상태를 고려하도록 하자.
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 74 75 76 77 78 | #include<stdio.h> #include<vector> #include<algorithm> #include<math.h> using namespace std; #define SIZE 300009 #define MOD 998244353 int V,E; vector<int> edge[SIZE]; int mark[SIZE]={0}; int is_possible=1,even=0,odd=0; void dfs(int node,int flag){ //flag=1 -> odd, 2 -> even mark[node]=flag; if(flag==1) odd++; else even++; for(int next:edge[node]){ if(mark[next]==0){ dfs(next,flag^3); //for 1->2->1->2... } else if(mark[next]!=(flag^3)){ is_possible=-1; return; } } return; } long long my_pow(int a,int b){ long long result=1; for(int i=1 ; i<=b ; i++){ result=(result*a)%MOD; } return result; } void clear(){ for(int i=1 ; i<=V ; i++){ edge[i].clear(); mark[i]=0; } is_possible=1; return; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d %d",&V,&E); for(int i=0 ; i<E ; i++){ int u,v; scanf("%d %d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } long long ans=1; for(int i=1 ; i<=V ; i++){ if(mark[i]==0){ even=0,odd=0; dfs(i,1); if(is_possible==-1) { break; } ans*=(my_pow(2,odd)+my_pow(2,even)); ans%=MOD; } } if(is_possible==-1) ans=0; printf("%lld\n",ans); clear(); } return 0; } | cs |
'Problem Solving > Graph' 카테고리의 다른 글
[Codeforces 954D] Fight Against Traffic (0) | 2019.05.20 |
---|---|
[Codeforces 1006E] Military Problem (0) | 2019.05.14 |
[Codeforces 1084D] The Fair Nut and the Best Path (0) | 2019.04.21 |
[Codeforces 1082D] Maximum Diameter Graph (0) | 2019.04.19 |
[Codeforces 1144F] Graph Without Long Directed Paths (0) | 2019.04.02 |