algorithm

BOJ 5021

rkawk 2022. 10. 10. 19:45

문제

더보기

μ™•μœ„ κ³„μŠΉ μ„±κ³΅λ‹€κ΅­μ–΄

ν•œκ΅­μ–΄   
1 초 128 MB 1005 340 255 34.884%

문제

μœ ν† ν”Όμ•„μ˜ 왕이 μ‚¬λ§ν–ˆλ‹€. 왕은 μžμ†μ„ 남기지 μ•Šκ³  μ‚¬λ§ν–ˆκΈ° λ•Œλ¬Έμ—, μ™•μœ„λ₯Ό κ³„μŠΉν•  μ‚¬λžŒμ„ μ§€λͺ©ν•˜μ§€ μ•Šμ•˜λ‹€. μ™•μ‹€ 귀쑱은 μ™•μœ„λ₯Ό μ£Όμž₯ν•˜κΈ° μ‹œμž‘ν–ˆλ‹€. μœ ν† ν”Όμ•„μ˜ λ²•μ—λŠ” μ™•μ˜ κ³„μŠΉμžκ°€ μ—†λŠ” κ²½μš°μ—, λ‚˜λΌλ₯Ό μ„Έμš΄ μ‚¬λžŒκ³Ό ν˜ˆν†΅μ΄ κ°€κΉŒμš΄ μ‚¬λžŒμ΄ μœ ν† ν”Όμ•„λ₯Ό ν†΅μΉ˜ν•œλ‹€λŠ” 쑰항이 μžˆλ‹€.

λ‚˜λΌλ₯Ό μ„Έμš΄ μ‚¬λžŒκ³Ό ν˜ˆν†΅μ΄ κ°€μž₯ κ°€κΉŒμš΄ μ‚¬λžŒμ€ 그의 μžμ†μ΄ μ•„λ‹Œ μ‚¬λžŒκ³Ό ν”Όκ°€ 덜 μ„žμΈ μ‚¬λžŒμ΄λ‹€. λͺ¨λ“  μ‚¬λžŒμ€ μ•„λ²„μ§€μ˜ ν˜ˆν†΅κ³Ό μ–΄λ¨Έλ‹ˆμ˜ ν˜ˆν†΅μ„ 반 μ”© λ°›κ²Œ λœλ‹€. λ‚˜λΌλ₯Ό μ„Έμš΄ μ‚¬λžŒμ˜ μžμ‹μ€ 1/2 왕쑱이며, κ·Έ 아듀이 왕쑱이 μ•„λ‹Œ μ‚¬λžŒκ³Ό κ²°ν˜Όν•œ κ²½μš°μ—λŠ” μ•„λ“€μ˜ μžμ‹μ€ 1/4 왕쑱이 λœλ‹€.

κ°€μž₯ λ‚˜λΌλ₯Ό μ„Έμš΄ μ‚¬λžŒκ³Ό ν˜ˆν†΅μ΄ κ°€κΉŒμš΄ μ‚¬λžŒμ„ μ°ΎλŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 

μž…λ ₯

첫째 쀄에 Nκ³Ό M이 μ£Όμ–΄μ§„λ‹€. (2 ≤ N, M ≤ 50)

λ‘˜μ§Έ 쀄에 μœ ν† ν”Όμ•„λ₯Ό μ„Έμš΄ μ‚¬λžŒμ˜ 이름이 μ£Όμ–΄μ§„λ‹€.

λ‹€μŒ N개 μ€„μ—λŠ” κ°€μ‘± 정보가 μ£Όμ–΄μ§„λ‹€. μ •λ³΄λŠ” 이름 μ„Έ 개둜 이루어져 있고, 곡백으둜 κ΅¬λΆ„λ˜μ–΄μ Έ μžˆλ‹€. 첫 번째 이름은 μžμ‹μ˜ 이름이고, λ’€μ˜ 두 이름은 λΆ€λͺ¨μ˜ 이름이닀.

λ‹€μŒ M개 μ€„μ—λŠ” μ™•μœ„λ₯Ό κ³„μŠΉλ°›κΈ°λ₯Ό μ£Όμž₯ν•˜λŠ” μ‚¬λžŒμ˜ 이름이 ν•œ 쀄에 ν•˜λ‚˜μ”© μ£Όμ–΄μ§„λ‹€.

λͺ¨λ“  이름은 1~10κΈ€μžμ΄λ©°, μ•ŒνŒŒλ²³ μ†Œλ¬Έμžλ‘œλ§Œ 이루어져 μžˆλ‹€. λ‚˜λΌλ₯Ό μ„Έμš΄ μ‚¬λžŒμ΄ μ™•μœ„λ₯Ό κ³„μŠΉν•˜λŠ” κ²½μš°λ‚˜, λˆ„κ΅°κ°€μ˜ μžμ‹μΈ κ²½μš°λŠ” μ—†λ‹€. 

좜λ ₯

첫째 쀄에 μœ ν† ν”Όμ•„λ₯Ό μ„Έμš΄ μ‚¬λžŒκ³Ό κ°€μž₯ ν˜ˆν†΅μ΄ κ°€κΉŒμš΄ μ‚¬λžŒμ˜ 이름을 좜λ ₯ν•œλ‹€. 항상 닡이 μœ μΌν•œ 경우만 μž…λ ₯으둜 μ£Όμ–΄μ§„λ‹€.

λ¬Έμ œμ— μ£Όμ–΄μ§€λŠ” κ°€μ‘± κ΄€κ³„λŠ” 성별, λ‚˜μ΄λ₯Ό κ³ λ €ν•˜μ§€ μ•Šκ³  λ§Œλ“€μ—ˆκΈ° λ•Œλ¬Έμ—, μ‹€μ œλ‘œλŠ” 말이 μ•ˆλ˜λŠ” κ²½μš°κ°€ λ‚˜μ˜¬ μˆ˜λ„ μžˆλ‹€. ν•˜μ§€λ§Œ, λͺ¨λ“  μžμ‹μ˜ λΆ€λͺ¨λŠ” μœ μΌν•˜λ©°, λ‹€μ‹œ μžμ‹μ΄ λΆ€λͺ¨μ˜ λΆ€λͺ¨κ°€ λ˜λŠ” κ²½μš°λ„ μ—†λ‹€. 또, ν•œ μ‚¬λžŒμ΄ μ—¬λŸ¬ λͺ…μ˜ μžμ‹μ΄ 될 수 도 μ—†λ‹€.

예제 μž…λ ₯ 1 λ³΅μ‚¬

9 2
edwardi
charlesi edwardi diana
philip charlesi mistress
wilhelm mary philip
matthew wilhelm helen
edwardii charlesi laura
alice laura charlesi
helen alice bernard
henrii edwardii roxane
charlesii elizabeth henrii
charlesii
matthew

예제 좜λ ₯ 1 λ³΅μ‚¬

matthew

예제 μž…λ ₯ 2 λ³΅μ‚¬

4 5
andrew
betsy andrew flora
carol andrew betsy
dora andrew carol
elena andrew dora
carol
dora
elena
flora
gloria

예제 좜λ ₯ 2 λ³΅μ‚¬

elena​

풀이

풀이 μžμ²΄λŠ” κ°„λ‹¨ν•˜λ‹€. 

λ¬Έμ œμ—μ„œ λͺ…μ‹œλ˜μ–΄ μžˆμ§€λŠ” μ•Šμ§€λ§Œ λΆ€λͺ¨ λ‘˜μ„ 아버지, μ–΄λ¨Έλ‹ˆλ‘œ 두고

(μ•„λ²„μ§€μ˜ ν˜ˆν†΅κ°’ + μ–΄λ¨Έλ‹ˆμ˜ ν˜ˆν†΅κ°’) * 1/2 λ₯Ό ν•œ 값이 μžλ…€μ˜ ν˜ˆν†΅μ˜ 값이 λœλ‹€.

이λ₯Ό λͺ¨λ“  μžλ…€μ— λŒ€ν•΄ 계산해주면 λ˜λŠ” λ¬Έμ œμ΄λ‹€.

 

μžλ…€μ™€ λΆ€λͺ¨μ— λŒ€ν•œ 정보가 ν•œλ²ˆμ— μž…λ ₯λ˜λ―€λ‘œ ꡬ쑰체둜 μ„ μ–Έν•΄μ€€λ‹€.

struct p{
    string name, parent1, parent2;
};

그리고 각각의 λ…Έλ“œ(μžλ…€, λΆ€λͺ¨ 각각의 이름) 의 ν˜ˆν†΅μ„ μ΄ˆκΈ°ν™”ν•΄μ£ΌκΈ° μœ„ν•΄ key-value table을 생성해쀀닀.

λΆ€λͺ¨μ™€ μžλ…€μ˜ 이름이 쀑볡될 수 있기 λ•Œλ¬Έμ—, 쀑볡일 κ²½μš°μ— insertλ₯Ό μ œν•œν•˜λŠ” map stl을 μ‚¬μš©ν•˜μ˜€λ‹€.

 

map<string,double>m;

 

μ„€λ¦½μžμ˜ ν˜ˆν†΅μ€ 1둜 μ΄ˆκΈ°ν™” ν•΄μ£Όκ³ , λ‚˜λ¨Έμ§€λŠ” λ‹€ 0으둜 μ΄ˆκΈ°ν™” ν•΄μ€€λ‹€.

cin>>founder;
    m.insert({founder, 1});
    for(int i=0; i<N; i++){
        p new_p;
        cin>>new_p.name>>new_p.parent1>>new_p.parent2;
        v.push_back(new_p);
        m.insert({new_p.name, 0});
        m.insert({new_p.parent1, 0});
        m.insert({new_p.parent2, 0});
    }

ν˜ˆν†΅μ΄ 0이 μ•„λ‹Œ κ²½μš°λŠ” 무쑰건 μ„€λ¦½μžμ™€ ν˜ˆμ—°κ΄€κ³„κ°€ μžˆμ–΄μ•Ό ν•˜λ―€λ‘œ queueλ₯Ό ν•˜λ‚˜ λ§Œλ“€μ–΄ μ„€λ¦½μžλ₯Ό λ„£μ–΄μ£Όκ³ ,

λΆ€λͺ¨κ°€ μ„€λ¦½μžμΈ κ²½μš°λΆ€ν„° 탐색해 λ‚˜κ°€λ„λ‘ ν–ˆλ‹€.

두λͺ…μ˜ λΆ€λͺ¨ 쀑 ν•˜λ‚˜λΌλ„ μ„€λ¦½μžμ΄λ©΄ ν˜ˆμ—°κ΄€κ³„λ₯Ό κ³„μ‚°ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ΄μ–΄μ§€λŠ” 것이닀.

λ‹€λ§Œ μ„€λ¦½μžμ˜ μžλ…€κ°€ μ„€λ¦½μžμ˜ λ°°μš°μžκ°€ λ˜λ“―μ΄ μ„€λ¦½μžμ™€ ν˜ˆμ—°κ΄€κ³„κ°€ μžˆλŠ” μ‚¬λžŒμ΄ μ„€λ¦½μžμ™€ ν˜ˆμ—°κ΄€κ³„κ°€ μžˆλŠ” μ‚¬λžŒμ˜ λ°°μš°μžκ°€ 될 수 μžˆμœΌλ―€λ‘œ μ„€λ¦½μžμ˜ μžλ…€, μ„€λ¦½μžμ˜ μžλ…€μ˜ μžλ…€ ~~~ λ₯Ό queue에 계속 λ„£μ–΄μ£Όλ©΄μ„œ 계산이 λ°”λ€ŒλŠ” κ²½μš°λ„ λͺ¨λ‘ 탐색해 주도둝 ν–ˆλ”°.

queue<string>q;
    q.push(founder);
    while(!q.empty()){
        string cur = q.front();
        q.pop();
        for(auto node : v){
            if(node.parent1 == cur || node.parent2 == cur){
                string p1 = node.parent1, p2 = node.parent2;
                double p1_rate = m.find(p1)->second, p2_rate = m.find(p2)->second;
                m.find(node.name)->second = (p1_rate+p2_rate)/2;
                q.push(node.name);
            }
        }
    }

이러면 λͺ¨λ“  μ‚¬λžŒμ˜ ν˜ˆμ—°κ΄€κ³„κ°€ κ΅¬ν•΄μ§€κ²Œ 되고, λ¬Έμ œκ°€ ν’€λ¦°λ‹€.

 

λ‹€λ₯Έ 풀이

λ‹€ ν’€κ³  λ‹€λ₯Έ 풀이λ₯Ό μ°Ύμ•„λ³΄μ•˜μ„λ•Œ

ν›„λ³΄μžλ₯Ό μž…λ ₯ν•˜λŠ” κ²½μš°μ— DFS둜 νƒμƒ‰ν•˜λŠ” 것이 더 μ½”λ“œκ°€ λͺ…λ£Œν•˜λ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆλ‹€.

 

λΆ€λͺ¨μ˜ ν˜ˆμ—°κ΄€κ³„λ₯Ό λΆ€λͺ¨μ˜ λΆ€λͺ¨κ°€ μ—†μ„λ•ŒκΉŒμ§€ 계산해 μžλ…€λ₯Ό κ³„μ‚°ν•˜λ©΄ λœλ‹€.

double dfs(string s){
    for(auto node : v){
        if(node.name == s){
            string p1 = node.parent1, p2 = node.parent2;
            double rate = (dfs(p1)+dfs(p2))/2;
            m[s] = rate;
            return rate;
        }
    }
    return m[s];
}

이 μ½”λ“œμ—μ„œλŠ” ꡬ쑰체 벑터 v의 μ›μ†Œμ˜ name이 μ—†μœΌλ©΄ λΆ€λͺ¨κ°€ μ—†λŠ” 것이기 λ•Œλ¬Έμ—, κ·Έλ•Œ map의 μ›μ†Œλ₯Ό λ°˜ν™˜ν•˜λ„λ‘ ν–ˆλ‹€.

 

전체 μ½”λ“œ

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
struct p{
    string name, parent1, parent2;
};
map<string,double>m;
vector<p>v;
int N, M;
double ans;
string founder, ans_s;
int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>N>>M;
    cin>>founder;
    m.insert({founder, 1});
    for(int i=0; i<N; i++){
        p new_p;
        cin>>new_p.name>>new_p.parent1>>new_p.parent2;
        v.push_back(new_p);
        m.insert({new_p.name, 0});
        m.insert({new_p.parent1, 0});
        m.insert({new_p.parent2, 0});
    }
    queue<string>q;
    q.push(founder);
    while(!q.empty()){
        string cur = q.front();
        q.pop();
        for(auto node : v){
            if(node.parent1 == cur || node.parent2 == cur){
                string p1 = node.parent1, p2 = node.parent2;
                double p1_rate = m.find(p1)->second, p2_rate = m.find(p2)->second;
                m.find(node.name)->second = (p1_rate+p2_rate)/2;
                q.push(node.name);
            }
        }
    }
    for(int i=0; i<M; i++){
        string s1;
        cin>>s1;
        for(auto iter = m.begin(); iter != m.end(); iter++){
            if(iter->first == s1){
                if(iter->second > ans){
                    ans = iter->second;
                    ans_s = iter->first;
                }
            }
        }
    }
    cout<<ans_s;
    
}
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <map>
using namespace std;
struct p{
    string name, parent1, parent2;
};
map<string,double>m;
vector<p>v;
int N, M;
double ans;
string founder, ans_s;
double dfs(string s){
    for(auto node : v){
        if(node.name == s){
            string p1 = node.parent1, p2 = node.parent2;
            double rate = (dfs(p1)+dfs(p2))/2;
            m[s] = rate;
            return rate;
        }
    }
    return m[s];
}
int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>N>>M;
    cin>>founder;
    m.insert({founder, 1});
    for(int i=0; i<N; i++){
        p new_p;
        cin>>new_p.name>>new_p.parent1>>new_p.parent2;
        v.push_back(new_p);
        m.insert({new_p.name, 0});
        m.insert({new_p.parent1, 0});
        m.insert({new_p.parent2, 0});
    }
    for(int i=0; i<M; i++){
        string s1;
        cin>>s1;
        double r=dfs(s1);
        if(r > ans){
            ans_s = s1;
            ans = r;
        }
    }
    cout<<ans_s;
    
}

 

포인트

ν˜ˆμ—°κ΄€κ³„μ™€ κ΄€λ ¨λœ λͺ¨λ“  λ³€μˆ˜λŠ” double둜 생성해주어야 ν•œλ‹€.

ansλ³€μˆ˜λ₯Ό int둜 μƒμ„±ν•΄μ„œ λ‘λ²ˆ ν‹€λ Έλ‹€.

 

map stl의 findν•¨μˆ˜κ°€ keyλ₯Ό μ°Ύμ§€ λͺ»ν–ˆμ„ 경우, map.end()λ₯Ό λ°˜ν™˜ν•œλ‹€λŠ” 것을 μƒκΈ°ν•˜μž.

map.end()λŠ” λ§ˆμ§€λ§‰ μ›μ†Œλ₯Ό μ°Έμ‘°ν•˜λŠ” 것이 μ•„λ‹Œ 반볡자의 λ§ˆμ§€λ§‰μ„ κ°€λ¦¬ν‚€λŠ” 것이닀.