티스토리 뷰

백준 4792 : 레드 블루 스패닝 트리

등급 : Platinum III

4792번: 레드 블루 스패닝 트리 (acmicpc.net)

 

4792번: 레드 블루 스패닝 트리

무방향, 무가중치, 연결 그래프가 주어진다. 그래프의 각 간선은 빨간색 또는 파란색으로 색칠되어져 있다. 이 그래프의 스패닝 트리 중 파란색 간선이 정확히 k개인 것이 있는지 없는지 알아내

www.acmicpc.net

사용 알고리즘 : Kruskal Algorithm

사용 자료구조 : Vector, Union-Find

 

크루스칼 알고리즘을 두 번 이용하여 스패닝 트리의 수정 가능성을 확인하는 문제였습니다.

위의 그래프를 예로 들어보자.

먼저 파란색 간선을 최소로 사용해주기 위해 빨간색으로 이뤄진 간선을 모두 이어준다.

이후 각 정점을 확인하며 연결을 하게 되면 위와 같은 스패닝 트리가 나타나게 된다.

이 때가 파란색 간선을 가장 적게 사용하는 경우이므로, 최솟값3이 된다.

 

두 번째로, 파란색 간선을 가장 많이 사용하는 경우를 보기 위해 파란색 간선으로만 스패닝 트리를 생성해본다.

이 때가 파란색 간선을 가장 많이 사용하는 경우이므로 최댓값5가 된다.

 ( 두 번째 단계를 진행할 때, 파란 간선을 모두 연결해도 스패닝 트리가 되지 않아도 상관 없다. )

 

이후 목표값이 이 범위 사이에 있다면 1, 그렇지 않다면 0을 출력해준다.

 ( 빨간 색 간선으로 바꿔주며 이 범위 내에 있는 파란 색 간선을 모두 표현할 수 있기 때문 )

<hide/>
#include <iostream>
#include <vector>

using namespace std;

int n, m, k;
int par[1001];
vector <pair <int, int>> v_r;
vector <pair <int, int>> v_b;

void init(int n)
{
    for (int i = 1; i <= n; i++)
    {
        par[i] = i;
    }
}

int find(int x)
{
    if (x == par[x]) return x;
    else return par[x] = find(par[x]);
}

bool uni(int x, int y)
{
    x = find(x);
    y = find(y);
    if (x == y) return false;
    else
    {
        par[x] = par[y] = min(x, y);
        return true;
    }
}

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

    int x, y, mini, maxi;
    string col;
    while (1)
    {
        cin >> n >> m >> k;
        if (n == 0 && m == 0 && k == 0) break;
        mini = 0;
        maxi = 0;
        v_r.clear();
        v_b.clear();
        init(n);
        for (int i = 0; i < m; i++)
        {
            cin >> col >> x >> y;
            if (col == "R") v_r.push_back({ x, y });
            else v_b.push_back({ x, y });
        }
        for (int i = 0; i < v_r.size(); i++)
        {
            uni(v_r[i].first, v_r[i].second);
        }
        for (int i = 0; i < v_b.size(); i++)
        {
            bool chk = uni(v_b[i].first, v_b[i].second);
            if (chk) mini++;
        }
        init(n);
        for (int i = 0; i < v_b.size(); i++)
        {
            if (uni(v_b[i].first, v_b[i].second)) maxi++;
        }

        if (mini <= k && k <= maxi) cout << 1 << "\n";
        else cout << 0 << "\n";
    }
}
<hide/>
import java.util.*;
import java.io.*;

public class Main{
    static List<int[]> v_r = new ArrayList<>();
    static List<int[]> v_b = new ArrayList<>();
    static int[] par = new int[1001];

    static void initPar(int n)
    {
        for(int i=1; i<=n; i++)
        {
            par[i] = i;
        }
    }
    static int find(int x)
    {
        if(x == par[x]) return x;
        else return par[x] = find(par[x]);
    }
    static boolean uni(int x, int y)
    {
        x = find(x);
        y = find(y);
        if(x == y) return false;
        else
        {
            par[x] = par[y] = Math.min(x, y);
            return true;
        }
    }
    static public void main(String[] agrs) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader (System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        int n, m, k, mini, maxi;
        
        while(true)
        {

            st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());
            m = Integer.parseInt(st.nextToken());
            k = Integer.parseInt(st.nextToken());
            if(n == 0 && m == 0 && k == 0) break;
            mini = 0;
            maxi = 0;
            for(int i=0; i<m; i++)
            {
                st = new StringTokenizer(br.readLine());
                if(st.nextToken().equals("B"))
                {
                    int[] arr = {Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())};
                    v_b.add(arr);
                }
                else
                {
                    int[] arr = {Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())};
                    v_r.add(arr);
                }

            }
            initPar(n);
            for(int i=0; i<v_r.size(); i++)
            {
                uni(v_r.get(i)[0], v_r.get(i)[1]);
            }
            for(int i=0; i<v_b.size(); i++)
            {
                if(uni(v_b.get(i)[0], v_b.get(i)[1])) mini++;
            }
            initPar(n);
            for(int i=0; i<v_b.size(); i++)
            {
                if(uni(v_b.get(i)[0], v_b.get(i)[1])) maxi++;
            }
            if(mini <= k && k <= maxi) sb.append(1).append("\n");
            else sb.append(0).append("\n");
            v_r.clear();
            v_b.clear();
        }
        System.out.println(sb);
    }
}
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함