티스토리 뷰
[CF 1118F1] Tree Cutting (Easy Version) - 1800
문제 설명 :
빨간색,파란색,무색(색깔 없음)노드로 이루어진 트리가 주어진다. 트리의 간선 (n-1)개 중에서 어느 한 간선을 제거했을 때 만들어지는 2개의 component가 있을텐데, 각 component를 이루는 노드의 색깔이 빨간색과 파란색이 동시에 존재하지 않도록 하는 간선이 몇 개인지 구하는 문제이다.
풀이 :
처음 생각한 것은 각 간선별로 하나씩 지워보고 만들어지는 2개의 component의 노드 색깔을 조사해볼까 생각해봤는데, 노드 수(간선 수)가 최대 30만이므로 이 풀이로는 힘들 것 같았다. 그래서 어떻게든 한 번의 순회만으로 제거할 수 있는 간선을 찾는 것이 유력하다고 생각했다.
정답을 만족시키는 두 component에서 어느 한 component에 빨간색(혹은 파란색)만 존재한다는 의미는 곧 또 다른 component에는 상반된 색깔인 파란색(혹은 빨간색)만 존재한다고 해석할 수 있다. 또한 이 경우에는 특정 색의 상반된 색의 개수는 반드시 0개여야만 하낟. 그래서 나는 dfs를 돌면서 subtree를 이루는 색깔 노드의 개수를 root에게 계속 전달해 가다가, 어떤 subtree에서의 색깔의 개수가 전체 색깔의 총 개수와 일치하면서 상반된 색깔의 개수가 0개라면 해당 간선을 지우는 것이 가능한 것이다.
주의할 점 :
-
배울 점 :
코드의 dfs부분에서 반환형이 pair<int,int>인데 first와 second는 각각 색깔의 수를 의미한다. dfs에서 parameter는 sub-dfs에게 전달해줄 내용을 갖고 있고, return type(pair<int,int>)는 sub-dfs가 root-dfs에게 전달해줄 내용을 갖고 있다.
아직 그래프문제는 같은 난이도의 타 유형에 비해서 취약한 것 같다. 앞으로 그래프 유형을 많이 풀어보면서 컨셉을 많이 접해보는 것이 중요할 것 같다. 다양한 컨셉을 접함으로써 그 유형의 다른 문제가 나왔을 때, 내가 취할 수 있는 연산이 어떤 것이 있는지 미리 대비해놓을 수 있기 때문이다.
코드 :
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 | #include<stdio.h> #include<math.h> #include<string.h> #include<iostream> #include<functional> #include<string> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<assert.h> #include<stdlib.h> #include<stack> using namespace std; /*********************Contest Template***********************/ typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<long long,long long> pll; #define FASTIO ios_base::sync_with_stdio(false);cin.tie(0); struct S{ int a,b; S(){}S(int _a,int _b) { a=_a; b=_b; } const bool operator<(const S &o) const{ return a<o.a;} }; priority_queue<int,vector<int>,greater<int>> mpq; const int SPACE=0,NL=1; string exm; inline void showAll(vector<int> &v,int sep){ //0=space,1="\n" for(int &here:v) printf("%d%c",here,(sep)?'\n':' '); } inline void exf(void){ cout<<exm<<"\n"; exit(0); } inline vector<int> int_seperation(int N,int d=10){ vector<int> v; while(N){v.push_back(N%d); N/=d;} reverse(v.begin(),v.end()); return v; } /*********************Contest Template***********************/ const int SIZE= 300009; int arr[SIZE],color[3]; vector<int> tree[SIZE]; int ans=0; pii dfs(int node,int par){ int _1=(arr[node]==1),_2=(arr[node]==2); for(int next:tree[node]){ if(par==next) continue; auto p=dfs(next,node); if(color[1]==p.first && p.second==0) ans++; if(color[2]==p.second && p.first==0) ans++; _1+=p.first,_2+=p.second; } return {_1,_2}; } int main(){ int n; scanf("%d",&n); for(int i=1 ; i<=n ; i++){ scanf("%d",&arr[i]); color[arr[i]]++; } for(int i=0 ; i<n-1 ; i++){ int u,v; scanf("%d %d",&u,&v); tree[u].push_back(v); tree[v].push_back(u); } dfs(1,0); printf("%d\n",ans); 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 |