중량제한

Wonseok Lee·2021년 10월 8일
0

Beakjoon Online Judge

목록 보기
49/117
post-thumbnail

Problem link: https://www.acmicpc.net/problem/1939

'한번에 얼마까지 보내볼 수 있겠어?'는 어려운 질문이지만, '한 번에 X만큼 보낼 수 있어?'는 쉬운 질문이다.

X 미만의 용량을 갖는 간선을 지워주고 출발지에서 목적지까지 도달 가능한지 BFS(또는 DFS)를 돌려주면 된다.

X의 범위는 1 ~ 1억까지이고 보낼 수 있는지의 여부를 표로 그려보면 대략 아래와 같을 것이다.

X...101112...1억
POSSIBLE?...TrueTrueFalse...False

따라서 X를 인덱스로 하여 이분 탐색을 진행하되 True의 Upperbound를 찾아주면 된다.

#include <iostream>
#include <vector>
#include <queue>

struct Edge
{
  size_t source_;
  size_t destination_;
  size_t capacity_;
  bool is_valid_;
};

using namespace std;

size_t N;
size_t M;
vector<Edge> EDGES;
vector<vector<Edge*> > MAP;
size_t S;
size_t D;

bool Bfs(void)
{
  vector<bool> visited(N, false);
  queue<size_t> q;

  visited[S - 1] = true;
  q.push(S - 1);

  while (!q.empty())
  {
    size_t here = q.front();
    q.pop();

    if (here == D - 1)
    {
      return true;
    }

    for (auto p_edge : MAP[here])
    {
      if (!p_edge->is_valid_)
      {
        continue;
      }

      size_t there = p_edge->destination_;
      if (!visited[there])
      {
        visited[there] = true;
        q.push(there);
      }
    }
  }

  return false;
}

size_t Solve(void)
{
  size_t left = 1;
  size_t right = 1000000000 + 1;

  while (left < right)
  {
    size_t middle = (left + right) / 2;

    for (auto& edge : EDGES)
    {
      if (edge.capacity_ < middle)
      {
        edge.is_valid_ = false;
      }
    }

    if (Bfs())
    {
      left = middle + 1;
    }
    else
    {
      right = middle;
    }

    for (auto& edge : EDGES)
    {
      edge.is_valid_ = true;
    }
  }

  return left - 1;
}

int main(void)
{
  // For Faster IO
  ios_base::sync_with_stdio(false);
  cout.tie(nullptr);
  cin.tie(nullptr);

  // Read Inputs
  cin >> N >> M;
  EDGES.assign(2 * M, Edge());
  MAP.assign(N, vector<Edge*>());

  for (size_t it = 0; it < M; ++it)
  {
    size_t src, dst, capa;
    cin >> src >> dst >> capa;

    EDGES[it].source_ = src - 1;
    EDGES[it].destination_ = dst - 1;
    EDGES[it].capacity_ = capa;
    EDGES[it].is_valid_ = true;

    EDGES[it + M].source_ = dst - 1;
    EDGES[it + M].destination_ = src - 1;
    EDGES[it + M].capacity_ = capa;
    EDGES[it + M].is_valid_ = true;

    MAP[src - 1].push_back(&EDGES[it]);
    MAP[dst - 1].push_back(&EDGES[it + M]);
  }

  cin >> S >> D;

  // Solve
  cout << Solve() << '\n';

  return 0;
}
profile
Pseudo-worker

0개의 댓글