알고리즘/1주일 1문제

2021년 4분기

tsyang 2022. 2. 20. 12:07

1. 프로그래머스 - 입실퇴실

더보기
#include <string>
#include <vector>
using namespace std;

vector<int> solution(vector<int> enter, vector<int> leave) {
	vector<int> answer(enter.size());
	vector<bool> room(enter.size());
	int num_people = 0;
	int leave_idx = 0;
	for(auto entry : enter)
	{
		//지금 방에있는애들 만남횟수 1증가
		int num_left_checked = num_people;
		for(size_t i=0 ; i < enter.size() && num_left_checked > 0;++i)
		{
			if (room[i] == true)
			{
				++answer[i];
				--num_left_checked;
			}
		}
		//신입추가
		room[entry - 1] = true;
		answer[entry - 1] += num_people;
		++num_people;

		//내보낼 수 있는만큼 다 내보낸다
		for( ;leave_idx < enter.size();++leave_idx)
		{
			int out = leave[leave_idx] - 1;
			if (room[out])
			{
				room[out] = false;
				--num_people;
			}
			else
				break;
		}
	}
	
	return answer;
}

2. 백준 2003 - 수들의 합 2 (투 포인터 알고리즘)

더보기
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	int N, M;
	cin >> N >> M;
	
	vector<int> nums(N);
	for(size_t ni = 0; ni < N ; ++ni)
		cin >> nums[ni];

	int l= 0, r = 0, sum = 0, ans = 0;
	while(true)
	{
		if (sum > M)
			sum -= nums[l++];
		else if (M == sum)
		{
			++ans;
			sum -= nums[l++];
		}
		else
		{
			if (r == N)	break;
			sum += nums[r++];
		}
	}
	cout << ans;
	
	return 0;
}

 

3. 백준 3079 - 입국심사 (이분 탐색)

더보기
#include <vector>
#include <iostream>
using namespace std;

int main()
{
	ios::sync_with_stdio(false);	cin.tie(nullptr); cout.tie(nullptr);

	int N, num;
	cin >> N >> num;
	vector<int> T(N);
	for(int k=0;k<N;++k) cin >> T[k];

	long long lo = 1, hi = 1000000000000000000; //10e18
	while(lo < hi)
	{
		const long long mid = (lo + hi) / 2;

		long long capability = 0;
		for(int k=0;k<N;++k)
		{
			capability += mid / T[k];
			if (capability >= num)
				break;
		}
		if(capability >= num)
			hi = mid;
		else
			lo = mid + 1;
	}

	cout << hi;
	return 0;
}

 

4. 백준 11657 - 타임머신 (벨만 포드)

더보기
#include <vector>
#include <iostream>
using namespace std;

const long long INF = 1e18;

struct Path
{
	int dst;
	int time;
	Path(int dst, int time) : dst{dst}, time{time}	{}
};

int main()
{
	ios::sync_with_stdio(false);	cin.tie(nullptr); cout.tie(nullptr);

	int N, M;
	cin >> N >> M;
	vector<vector<Path>> paths(N+1);

	for(int i=0;i<M;++i)
	{
		int from, to, cost;
		cin >> from >> to >> cost;
		paths[from].emplace_back(to, cost);
	}

	vector<long long> times(N + 1, INF);
	times[1] = 0;

	for(int cnt=0;cnt<N;++cnt)
		for(int i=1;i <= N;++i)
			for(const auto &path : paths[i])
				if(times[i] != INF)
				{
					long long newCost = times[i] + path.time;
					if(newCost < times[path.dst])
					{
						times[path.dst] = newCost;
					}
				}

	for (int i = 1; i <= N; ++i)
		for (const auto &path : paths[i])
			if (times[i] != INF)
			{
				long long newTime = times[i] + path.time;
				if (newTime < times[path.dst])
				{
					cout << -1;
					return 0;
				}
			}
	for(int i=2;i<=N;++i)
	{
		if (times[i] == INF) cout << "-1\n";
		else cout << times[i] << "\n";
	}
	
	return 0;
}

 

5. 백준 2336 - 굉장한 학생 (세그먼트 트리)

더보기
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

constexpr int treeSize = 500001;
constexpr int INF = 987654321;

struct student
{
	int x, y, z;

	bool operator<(const student& rhs)
	{
		return x < rhs.x;
	}
};

void update(int idx, int val, vector<int> & tree)
{
	idx += treeSize;
	tree[idx] = min(tree[idx], val);
	while (idx > 1) {
		idx >>= 1;
		tree[idx] = min(tree[idx << 1], tree[idx << 1 | 1]);
	}
}

int query(int left, int right, const vector<int> & tree)
{
	int ret = INF;
	for (left += treeSize, right += treeSize; left <= right; left >>= 1, right >>= 1) {
		if (left % 2 == 1) {
			ret = min(ret, tree[left++]);
		}
		if (right % 2 == 0) {
			ret = min(ret, tree[right--]);
		}
	}
	return ret;
}


int main()
{
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int N;
	cin >> N;

	vector<int> tree(treeSize << 1, INF);
	vector<student> students(treeSize);
	
	int rank;
	for (int i = 1; i <= N; ++i) {
		cin >> rank;
		students[rank].x = i;
	}
	for (int i = 1; i <= N; ++i) {
		cin >> rank;
		students[rank].y = i;
	}
	for (int i = 1; i <= N; ++i) {
		cin >> rank;
		students[rank].z = i;
	}

	sort(students.begin()+1, students.begin() + N + 1);

	int num_losers = 0;
	for (int i = 1; i <= N; i++) {
		int rank3rd = query(0, students[i].y - 1, tree);
		if (rank3rd != INF && rank3rd < students[i].z) {
			num_losers++;
		}

		update(students[i].y, students[i].z, tree);
	}

	cout << N - num_losers << '\n';
	return 0;
}

 

6. 백준 11403 - 경로 찾기 (플로이드 와샬)

더보기
#include <iostream>
#include <vector>

using namespace std;

int main()
{
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	
	int N;
	cin >> N;
	vector<vector<bool>> graph(N, vector<bool>(N, false));
	for (int i = 0; i < N; ++i)
		for (int j = 0; j < N; ++j)
		{
			int hasPath;
			cin >> hasPath;
			graph[i][j] = hasPath == 1;
		}

	for(int k=0;k<N;++k)
		for(int i=0;i<N;++i)
			for(int j=0;j<N;++j)
				graph[i][j] = graph[i][j] || (graph[i][k] && graph[k][j]);

	for(int i=0;i<N;++i)
	{
		for (int j = 0; j < N; ++j)
			cout << (graph[i][j] ? 1 : 0) << ' ';
		cout << "\n";
	}
	
	return 0;
}

 

7. 프로그래머스 - 행렬 테두리 회전하기

더보기
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<int>> make_matrix(size_t rows, size_t columns)
{
	int cnt = 1;
	vector<vector<int>> ret(rows, vector<int>(columns));
	for (size_t i = 0; i < rows; ++i)
		for (size_t j = 0; j < columns; ++j)
			ret[i][j] = cnt++;
	return ret;
}

vector<pair<int, int>> get_coords_to_rotate(int x1, int y1, int x2, int y2)
{
	vector<pair<int, int>> coords;
	const int predicted_size = (x2 - x1 + 1) * 2 + (y2 - y1 + 1) * 2 - 1;
	coords.reserve(predicted_size);

	for (int x = x1 - 1; x < x2 - 1; ++x)
		coords.emplace_back(x, y1 - 1);
	for (int y = y1 - 1; y < y2 - 1; ++y)
		coords.emplace_back(x2 - 1, y);
	for (int x = x2 - 1; x > x1 - 1; --x)
		coords.emplace_back(x, y2 - 1);
	for (int y = y2 - 1; y > y1 - 1; --y)
		coords.emplace_back(x1 - 1, y);
	return coords;
}

void rotate(vector<vector<int>> & matrix, const vector<int> & query, vector<int> & result)
{
	auto coords = get_coords_to_rotate(query[1], query[0], query[3], query[2]);
	int len = coords.size();
	int prev = matrix[coords[len-1].second][coords[len - 1].first];
	int min = prev;
	for(int i=0;i<len;++i)
	{
		swap(prev, matrix[coords[i].second][coords[i].first]);
		if (prev < min)
			min = prev;
	}
	result.emplace_back(min);
}

vector<int> solution(int rows, int columns, vector<vector<int>> queries) {
	vector<int> answer;
	auto mat = make_matrix(rows, columns);
	for(auto query : queries)
	{
		rotate(mat, query, answer);
	}
	return answer;
}

 

8. 백준 17412 - 도시 왕복하기1 (네트워크 유량)

더보기
#include <vector>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

constexpr int MAX = 401;
constexpr int SOURCE = 1;
constexpr int SINK = 2;
int c[MAX][MAX];
int f[MAX][MAX];
vector<int> paths[MAX];

int r(int from, int to)
{
	return c[from][to] - f[from][to];
}

bool try_flow()
{
	vector<int> parent(MAX, -1);
	queue<int> q;
	q.emplace(SOURCE);

	while(false == q.empty())
	{
		int here = q.front(); q.pop();
		if (here == SINK) break;
		
		for(int there : paths[here])
		{
			if(r(here,there) > 0 && parent[there] == -1)
			{
				parent[there] = here;
				q.emplace(there);
			}
		}
	}

	if (parent[SINK] == -1) return false;

	for(int to = SINK; to != SOURCE ; to = parent[to])
	{
		int from = parent[to];
		++f[from][to];
		--f[to][from];
	}
	return true;
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	size_t N, P;
	cin >> N >> P;
	int from, to;
	memset(c, 0x00, sizeof(c));
	memset(f, 0x00, sizeof(f));
	for(size_t cnt=0;cnt < P;++cnt)
	{
		int from, to;
		cin >> from >> to;
		c[from][to] = 1;
		paths[from].emplace_back(to);
		paths[to].emplace_back(from);
	}
	int ans = 0;
	
	while(try_flow())
		++ans;
	
	cout << ans;
	return 0;
}

 

9. 백준 14942 - 개미 (희소 테이블)

더보기
#include <iostream>
#include <vector>

constexpr int MAX = 100001;
using namespace std;

class Solver
{
public :
	void solve()
	{
		read();
		calc_answer();
		print_answer();
	}

private:
	void read()
	{
		cin >> n;
		path.resize(n + 1);
		energy.resize(n + 1);
		answer.resize(n + 1);
		
		for (int i = 1; i <= n; i++)
			cin >> energy[i];

		for (int i = 0; i < n - 1; i++) {
			int a, b, c;
			cin >> a >> b >> c;

			path[a].emplace_back(b, c);
			path[b].emplace_back(a, c);
		}
	}

	void calc_answer()
	{
		vector<pair<int, int>> costs{ { 0, 0 } };
		dfs(1, 0, costs);
		answer[1] = 1;
	}

	void print_answer()
	{
		for (int i = 1; i <= n; i++)
			cout << answer[i] << '\n';
	}

	int binary_search(vector<pair<int, int>>& costs, int energy)
	{
		int lastValue = costs.back().second;

		int left = 0, right = costs.size() - 1;
		while (left + 1 < right) {
			int mid = (left + right) / 2;

			int idx = mid - 1 >= 0 ? mid - 1 : 0;
			
			int curTarget = lastValue - costs[idx].second;
			if (curTarget <= energy)
				right = mid;
			else
				left = mid;
		}
		int idx = right - 1 >= 0 ? right - 1 : 0;
		if (lastValue - costs[idx].second > energy)
			return -1;
		
		return right;
	}

	void dfs(int from, int to, vector<pair<int, int>>& costs)
	{
		int closest = binary_search(costs, energy[from]);
		if (closest == -1)
			answer[from] = from;
		else
			answer[from] = costs[closest].first;

		for (auto& adj : path[from]) {
			if (adj.first != to) {
				costs.emplace_back(from, costs.back().second + adj.second);
				dfs(adj.first, from, costs);
				costs.pop_back();
			}
		}
	}

private:
	int n;
	vector<int> answer;
	vector<int> energy;
	vector<vector<pair<int, int>>> path;
};

int main(void)
{
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	Solver().solve();
	return 0;
}

10. 백준 13161 - 분단의 슬픔 (디닉 알고리즘)

더보기
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

constexpr int MAX = 502;
constexpr int SOURCE = 0;
int SINK = -1;
constexpr int NONE = -1;
constexpr int INF = 987654321;
int N;

int C[MAX][MAX];
int F[MAX][MAX];
int group[MAX];	// 1 : A진영, 2: B진영, 0: 상관없음.
constexpr int A = 1, B = 2, DC = 0;

int level[MAX];

void read()
{
	cin >> N;
	SINK = N + 1;
	for (int i = 1; i <= N; ++i)
		cin >> group[i];
	for (int i = 1; i <= N; ++i)
		for (int j = 1; j <= N; ++j)
			cin >> C[i][j];

	group[SINK] = group[SOURCE] = DC;

	//source, sink끼리 묶어줌
	for (int i = 0; i <= SINK; ++i)
	{
		int sum_source = 0, sum_sink = 0;
		if (group[i] == DC)
		{
			for (int j = 1; j <= N; ++j)
			{
				if (group[j] == A)
					sum_source += C[i][j];
				else if (group[j] == B)
					sum_sink += C[i][j];
			}
		}
		C[SOURCE][i] = C[i][SOURCE] = sum_source;
		C[i][SINK] = C[SINK][i] = sum_sink;
	}
}

int calc_base_cost()
{
	int base = 0;
	for(int i=1;i<=N;++i)
	{
		if (group[i] == A)
		{
			for (int j = 1; j <= N; ++j)
			{
				if(group[j] == B)
				{
					base += C[i][j];
				}
			}
		}

	}
	return base;
}

void TEST_read()
{
	for (int i = 1; i <= N; ++i)
	{
		if (group[i] == DC)
		{
			cout << "for " << i << " : " << " SOURCE = " << C[SOURCE][i] << " , SINK = " << C[i][SINK] << endl;
		}
	}
}

void calc_level()
{
	//bfs 방식으로 레벨 세팅
	queue<int> q;
	level[SOURCE] = 0;
	level[SINK] = NONE;
	for (int i = 1; i <= N; ++i)
		level[i] = NONE;

	q.emplace(SOURCE);
	int cur_level = 0;
	while (false == q.empty())
	{
		++cur_level;

		int cur = q.front(); q.pop();

		for (int i = 1; i <= SINK; ++i)
		{
			if (level[i] == NONE && group[i] == DC) //도달한적 없음
			{
				int res = C[cur][i] - F[cur][i];
				if (res > 0) //잔여용량 있음
				{
					q.emplace(i);
					level[i] = cur_level;
				}
			}
		}
	}
}

void print_level()
{
	cout << "CALC LEVEL : ";
	for (int i = SOURCE; i <= SINK; ++i)
	{
		cout << level[i] << " ";
	}
	cout << endl;
}

int flow_to_sink(int cur, int cur_flow, vector<int> & last_visited)
{
	if (cur == SINK) return cur_flow;

	for(int i=last_visited[cur] + 1;i<=SINK;++i)
	{
		last_visited[cur] = i;
		if (group[i] != DC) continue;
		if (level[cur] + 1 != level[i]) continue;
		int res = C[cur][i] - F[cur][i];
		if (res <= 0) continue;
		if (cur_flow > res)
			cur_flow = res;
		int flow_sent = flow_to_sink(i, cur_flow, last_visited);
		if(flow_sent > 0)
		{
			F[cur][i] += flow_sent;
			F[i][cur] -= flow_sent;
			return flow_sent;
		}
		
	}
	return 0;
}

vector<bool> calc_is_A_side()
{
	vector<bool> visited(MAX, false);

	queue<int> q;
	visited[SOURCE] = true;
	q.emplace(SOURCE);
	while(false == q.empty())
	{
		int cur = q.front(); q.pop();
		for(int i=1;i<=N;++i)
		{
			if (visited[i] || group[i] != DC) continue;
			int res = C[cur][i] - F[cur][i];
			if(res > 0)
			{
				visited[i] = true;
				q.emplace(i);
			}
		}
	}
	for(int i=1;i<=N;++i)
	{
		if (group[i] == A) visited[i] = true;
		else if (group[i] == B) visited[i] == false; 
	}
	return visited;
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);

	read();
	int max_flow = calc_base_cost();

	while(true)
	{
		calc_level();
		if (level[SINK] == NONE) break;
		vector<int> last_visited(SINK, 0);
		while(true)
		{
			int flow_sent = flow_to_sink(SOURCE, INF, last_visited);
			if (flow_sent == 0) break;
			max_flow += flow_sent;
		}
	}

	cout <<max_flow << "\n";
	auto is_A_side = calc_is_A_side();

	for(int i=1;i<=N;++i)
		if (is_A_side[i]) cout << i << " ";
	cout << "\n";
	
	for (int i = 1; i <= N; ++i)
		if (false == is_A_side[i]) cout << i << " ";
	cout << "\n";
	
	return 0;
}

 

11. 백준 1298 - 노트북의 주인을 찾아서 (이분 매칭)

더보기
#include <iostream>
#include <vector>

using namespace std;

constexpr int NONE = -1;

int N;
vector<vector<int>> adjs;
vector<int> bMatch;

bool dfs(int a, vector<bool>& visited)
{
	if (visited[a]) return false;
	visited[a] = true;
	
	for(auto b : adjs[a])
	{
		if(bMatch[b] == NONE || dfs(bMatch[b], visited))
		{
			bMatch[b] = a;
			return true;
		}
	}

	return false;
}

int main()
{
	int M;
	cin >> N >> M;

	adjs.resize(N+1);
	bMatch.resize(N + 1, NONE);
	
	while(M-- > 0)
	{
		int a, b;
		cin >> a >> b;
		adjs[a].emplace_back(b);
	}

	int ans = 0;
	for(int i=1;i<=N;++i)
	{
		vector<bool> visited(N + 1, false);
		if(dfs(i, visited))
			++ans;
	}
	cout<<ans;
	return 0;
}

 

12. 백준 11408 - 열혈강호 5 (MCMF (SPFA))

더보기
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

vector<vector<int>> c, f; //capacity, flow
vector<vector<pair<int,int>>> adj; //first = 타겟 정점, second = 비용

constexpr int INF = 987654321;

int src = 0, snk = 0;

int N, M;

int m2idx(int m)
{
	return m + N;
}

void read()
{
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	cin >> N >> M;
	//일(M)은 마지막 직원 다음의 인덱스부터 시작  (예, 직원 5명 일 7개면 첫 번째일의 인덱스는 6, 마지막은 12, 싱크는 13)
	snk = N + M + 1;
	c.resize(snk + 1, vector<int>(snk + 1, 0));
	f.resize(snk + 1, vector<int>(snk + 1, 0));
	adj.resize(snk + 1);
	for (int u = 1; u <= N; ++u)
	{
		int num_work;
		cin >> num_work;
		while (num_work-- > 0)
		{
			int v, cost;
			cin >> v >> cost;
			v += N;	//일의 인덱스는 마지막 직원의 인덱스 다음부터 시작	
			adj[u].emplace_back(v, cost);
			adj[v].emplace_back(u, -cost);	//역방향은 음의 비용
			c[u][v] = 1;
		}
		adj[src].emplace_back(u, 0);	//소스->직원 으로 가는 경로 추가
		c[src][u] = 1;
	}
	for(int m = N + 1 ; m < snk ; ++m)
	{
		adj[m].emplace_back(snk, 0); //일-> 싱크로의 경로 추가
		c[m][snk] = 1;
	}

}

int flow_once() //SPFA 알고리즘 사용, 벨먼포드도 가능
{
	vector<int> parent(snk + 1, -1);
	vector<bool> isInQ(snk + 1, false);
	vector<int> costs(snk + 1, INF);
	queue<int> q;
	
	costs[src] = 0;
	isInQ[src] = true;
	q.emplace(src);
	
	while(false == q.empty())
	{
		int u = q.front(); q.pop();
		isInQ[u] = false;
		for(auto e : adj[u])
		{
			int v = e.first;
			int cost = e.second;

			int r = c[u][v] - f[u][v];
			if (r <= 0) continue;

			int new_cost = costs[u] + cost;
			if (new_cost >= costs[v]) continue;

			costs[v] = new_cost;
			parent[v] = u;
			if(false == isInQ[v])
			{
				q.emplace(v);
				isInQ[v] = true;
			}
		}
	}
	if (parent[snk] == -1)	//더이상 경로 없음
		return -1;

	//여기서는 snk로 가는 최단경로가 구해져 있어야 한다.
	for(int v = snk; v != src; v=parent[v])
	{
		int u = parent[v];
		++f[u][v];
		--f[v][u];	//1씩 흘려준다.
	}

	return costs[snk];
}

int main()
{
	read();
	int num_work = 0, total_cost = 0;
	while(true)
	{
		int cost = flow_once();
		if (cost == -1) break;
		++num_work;
		total_cost += cost;
	}
	cout << num_work << "\n" << total_cost;

	return 0;
}

 

13. 백준 11585 - 속타는 저녁 메뉴 (KMP)

더보기
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

vector<int> get_p(const vector<char> & str)
{
	vector<int> p(str.size(), 0);

	int j = 0;
	for(size_t i = 1; i < str.size();++i)
	{
		while(j>0 && str[i] != str[j])
			j = p[j - 1];
		if (str[i] == str[j])
			p[i] = ++j;
	}
	return p;
}

int count_match(const vector<char> & src, const vector<char> & target)
{
	int cnt = 0;

	auto p = get_p(target);
	size_t j = 0;
	const size_t len = src.size() * 2 - 1;
	for(size_t i = 0;i<len;++i)
	{
		const auto idx = i % src.size();
		while (j > 0 && src[idx] != target[j])
			j = p[j - 1];
		if(src[idx]==target[j])
		{
			if (j == target.size() - 1)
			{
				++cnt;
				j = p[j];
			}
			else
				++j;
		}
	}

	return cnt;
}

int get_gcd(int a, int b)
{
	if (b == 0) return a;
	return get_gcd(b, a%b);
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	int N; cin >> N;
	vector<char> target(N);
	vector<char> src(N);

	for(int i =0;i<N;++i)
		cin >> target[i];
	for (int i = 0; i < N; ++i)
		cin >> src[i];

	int n = 0, d = N;
	n = count_match(src, target);
	const int gcd = get_gcd(d, n);
	n /= gcd;
	d /= gcd;
	cout << n << '/' << d;

	return 0;
}

 

14. 백준 3736 - System Engineer (호프크로프트-카프 알고리즘)

더보기
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

struct Data
{
public:
	Data(int n)
	{
		N = n;
		A.resize(N, -1);
		B.resize(N, -1);
		a_level.resize(N, -1);
		adj.resize(N);
		matched.resize(N);
	}

	int N;
	vector<bool> matched;
	vector<int> A, B, a_level;
	vector<vector<int>> adj;
};

void set_level(Data& data)
{
	queue<int> q;

	for(int a=0;a<data.N;++a)
	{
		if (false == data.matched[a])
		{
			data.a_level[a] = 0;
			q.emplace(a);
		}
		else
			data.a_level[a] = -1;
	}

	while(false == q.empty())
	{
		int a = q.front(); q.pop();

		for(int b : data.adj[a])
		{
			if(data.B[b] != -1 && data.a_level[data.B[b]] == -1)
			{
				data.a_level[data.B[b]] = data.a_level[a] + 1;
				q.push(data.B[b]);
			}
		}
	}
}

bool set_aug_flow(int a, Data& data)
{
	for(int b : data.adj[a])
	{
		//매칭이 아직 안 됐거나, 증가경로에 포함 가능한 매칭
		if(data.B[b] == -1 || 
			data.a_level[data.B[b]] == data.a_level[a] + 1 && set_aug_flow(data.B[b], data))
		{
			data.matched[a] = true;
			data.A[a] = b;
			data.B[b] = a;
			return true;
		}
	}
	return false;
}

int main()
{
	int N;
	while (scanf("%d", &N) > 0) 
	{
		Data data(N);
		for (int i = 0; i < N; i++) {
			int job, J;
			scanf("%d: (%d)", &job, &J);
			for (int j = 0; j < J; j++) {
				int server;
				scanf("%d", &server);
				data.adj[job].push_back(server - N);
			}
		}
		int num_match = 0;
		while(true)
		{
			set_level(data);

			int num_aug_flow = 0;
			for(int a = 0 ; a < N; ++a)
			{
				if (false == data.matched[a] && set_aug_flow(a, data))
					++num_aug_flow;
			}

			if (num_aug_flow == 0) break;
			num_match += num_aug_flow;
		}
		printf("%d\n", num_match);
	}
	
	return 0;
}

 

 

'알고리즘 > 1주일 1문제' 카테고리의 다른 글

2022년 2분기  (0) 2023.01.23
2022년 1분기  (0) 2023.01.23
2021년 3분기  (0) 2021.10.22
2021년 2분기  (0) 2021.10.22
2021년 1분기  (1) 2021.01.24