제출 #543591

#제출 시각아이디문제언어결과실행 시간메모리
543591aryan12One-Way Streets (CEOI17_oneway)C++17
100 / 100
696 ms74640 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N = 1e5 + 5;

//INPUT
vector<pair<int, int> > g[N];
vector<pair<int, int> > conditions;
map<int, pair<int, int> > edge_index;

//BRIDGE FINDING
int disc[N], low[N];
set<int> bridges; //edge index
int tim = 0;
set<pair<int, int> > actually_multiple;

//DFS
bool vis[N]; //vis[edge index]
bool vis2[N];

//ANSWER
vector<int> answer(N, -2);
/*
= 0 --> B
= 1 --> R
= -1 --> L
*/

//BRIDGE TREE RELATED
int component_number[N]; //the component number of the node
vector<pair<int, int> > bridge_tree[N]; //connects component number only
int depth[N];
int DP[19][N];

//FOR UFDS
int ufds_parent[N];

int Find(int x)
{
	if(x == ufds_parent[x])
	{
		return x;
	}
	return ufds_parent[x] = Find(ufds_parent[x]);
}

void Unite(int a, int b)
{
	a = Find(a), b = Find(b);
	ufds_parent[a] = b;
}

void dfs(int node, int par)
{
	vis2[node] = true;
	disc[node] = ++tim;
	low[node] = tim;
	//cout << "node = " << node << ", time = " << tim << "\n";

	for(auto i: g[node])
	{
		int to = i.first, edge_idx = i.second;

		if(to == par)
		{
			continue;
		}

		if(vis2[to])
		{
			low[node] = min(low[node], disc[to]);
			continue;
		}

		vis[edge_idx] = true;
		dfs(to, node);
		low[node] = min(low[node], low[to]);

		if(disc[node] < low[to] && !actually_multiple.count({min(node, to), max(node, to)}))
		{
			bridges.insert(edge_idx);
		}

		/*if(node == 5 && to == 6)
		{
			cout << disc[node] << " " << low[to] << "\n";
		}*/
	}
}

//in dfs2 --> vis[node]

void dfs2(int node, int par, int component)
{
	vis[node] = true;
	component_number[node] = component;
	for(auto i: g[node])
	{
		int to = i.first, edge_idx = i.second;
		if(!vis[to] && !bridges.count(edge_idx))
		{
			dfs2(to, node, component);
		}
	}
}

void dfs_component(int node, int par)
{
	vis2[node] = true;
	for(auto i: bridge_tree[node])
	{
		int to = i.first, edge_idx = i.second;
		if(to != par)
		{
			depth[to] = depth[node] + 1;
			DP[0][to] = node;
			dfs_component(to, node);
		}
	}
}

int LCA(int x, int y)
{
	/*int f = 0;
	if(x == 2 && y == 6)
	{
		cout << "LCA: " << depth[x] << " " << depth[y] << "\n";
		f = 1;
	}*/
	if(depth[x] > depth[y])
	{
		swap(x, y);
	}
	int diff = depth[y] - depth[x];
	for(int i = 18; i >= 0; i--)
	{
		if(diff >= (1 << i))
		{
			diff -= (1 << i);
			y = DP[i][y];
		}
	}
	/*if(f == 1)
	{
		cout << "now: " << x << ", " << y << "\n";
	}*/
	if(x == y)
	{
		return x;
	}
	for(int i = 18; i >= 0; i--)
	{
		if(DP[i][x] != DP[i][y])
		{
			x = DP[i][x];
			y = DP[i][y];
		}
	}
	return DP[0][x];
}

void Solve() 
{
	int n, m;
	cin >> n >> m;

	for(int i = 1; i <= n; i++)
	{
		ufds_parent[i] = i;
	}

	set<pair<int, int> > multiple_occurrences;

	set<int> to_be_considered;

	for(int i = 1; i <= m; i++)
	{
		int u, v, f = 0;
		cin >> u >> v;

		if(u < v)
		{
			f = 1;
			swap(u, v);
		}

		if(!multiple_occurrences.count({v, u}) && v != u) //removing all multiple and self edges
		{
			multiple_occurrences.insert({v, u});
			g[u].push_back(make_pair(v, i));
			g[v].push_back(make_pair(u, i));
			to_be_considered.insert(i);
		}

		else 
		{
			answer[i] = 0;
			if(v != u)
			{
				actually_multiple.insert({v, u});
			}
		}

		if(f == 1)
		{
			swap(u, v);
		}

		edge_index[i] = {u, v};
	}

	/*for(auto i: actually_multiple)
	{
		cout << i.first << " " << i.second << "\n";
	}

	cout << "actually_multiple over" << endl;*/

	for(int i = 1; i <= n; i++)
	{
		if(!vis2[i])
		{
			dfs(i, -1);
		}
	}

	/*for(auto i: bridges)
	{
		cout << edge_index[i].first << " " << edge_index[i].second << "\n";
	}

	cout << "bridges over" << endl;*/

	for(int i = 0; i < N; i++)
	{
		vis[i] = false;
	}

	int component = 1;
	for(int i = 1; i <= n; i++)
	{
		if(!vis[i])
		{
			dfs2(i, -1, component++);
		}
	}

	for(int i = 1; i <= m; i++)
	{

		if(edge_index[i].first == edge_index[i].second || !to_be_considered.count(i))
		{
			continue;
		}

		if(component_number[edge_index[i].first] != component_number[edge_index[i].second])
		{
			bridge_tree[component_number[edge_index[i].first]].push_back(make_pair(component_number[edge_index[i].second], i));
			bridge_tree[component_number[edge_index[i].second]].push_back(make_pair(component_number[edge_index[i].first], i));
		}

		else
		{
			answer[i] = 0;
		}

	}

	int p;
	cin >> p;
	for(int i = 1; i <= p; i++)
	{
		int start, dest;
		cin >> start >> dest;
		start = component_number[start];
		dest = component_number[dest];
		
		if(start != dest)
		{
			//cout << "conditions: " << start << ", " << dest << "\n";
			conditions.push_back(make_pair(start, dest));
		}
	}

	/*for(int i = 0; i < conditions.size(); i++)
	{
		cout << conditions[i].first << " " << conditions[i].second << "\n";
	}

	for(int i = 1; i <= n; i++)
	{
		cout << component_number[i] << " ";
	}
	cout << endl;

	cout << component << "\n";

	cout << "bridge tree output\n";
	for(int i = 1; i < component; i++)
	{
		for(int j = 0; j < bridge_tree[i].size(); j++)
		{
			cout << i << " " << bridge_tree[i][j].first << "\n";
		}
	}*/

	//cout << "bye" << endl;

	for(int i = 1; i <= n; i++) 
	{
		vis2[i] = false;
	}

	for(int i = 1; i < component; i++)
	{
		if(!vis2[i])
		{
			depth[i] = 0;
			DP[0][i] = -1;
			dfs_component(i, -1);
		}
	}

	//cout << "hi" << endl;
	for(int i = 1; i < 18; i++)
	{
		for(int j = 1; j < component; j++)
		{
			if(DP[i - 1][j] == -1)
			{
				DP[i][j] = -1;
			}
			else 
			{
				DP[i][j] = DP[i - 1][DP[i - 1][j]];
			}
		}
	}

	/*for(int i = 0; i < 18; i++) 
	{
		for(int j = 1; j < component; j++)
		{
			cout << DP[i][j] << " ";
		}
		cout << "\n";
	}*/

	set<pair<int, int> > should_be_satisfied;

	//cout << "doing conditions" << endl;
	for(int i = 0; i < conditions.size(); i++)
	{
		int lca = LCA(conditions[i].first, conditions[i].second);
		int node = conditions[i].first;

		//cout << "conditions[i].first = " << conditions[i].first << ", conditions[i].second = " << conditions[i].second << ", lca = " << lca << "\n";

		node = Find(node);
		while(depth[node] > depth[lca])
		{
			should_be_satisfied.insert(make_pair(node, DP[0][node]));
			Unite(node, DP[0][node]);
			//cout << node << " -> " << DP[0][node] << "\n";
			node = Find(node);
		}

		node = Find(conditions[i].second);
		while(depth[node] > depth[lca])
		{
			should_be_satisfied.insert(make_pair(DP[0][node], node));
			//cout << node << " <- " << DP[0][node] << "\n";
			Unite(node, DP[0][node]);
			node = Find(node);
		}
	}

	//cout << "reached here" << endl;
	for(int i = 1; i <= m; i++)
	{
		int x = component_number[edge_index[i].first], y = component_number[edge_index[i].second];
		//cout << "x = " << x << ", y = " << y << "\n";
		answer[i] = 0;
		if(x != y)
		{
			if(should_be_satisfied.count({x, y}))
			{
				answer[i] = 1;
			}
			else if(should_be_satisfied.count({y, x}))
			{
				answer[i] = -1;
			}
		}
		if(actually_multiple.count({min(edge_index[i].first, edge_index[i].second), max(edge_index[i].first, edge_index[i].second)}))
		{
			answer[i] = 0;
		}
		if(answer[i] == -1)
		{
			cout << "L";
		}
		else if(answer[i] == 1)
		{
			cout << "R";
		}
		else {
			cout << "B";
		}
	}
	cout << "\n";
}

int32_t main() 
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	Solve();
	return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

oneway.cpp: In function 'void dfs_component(long long int, long long int)':
oneway.cpp:113:21: warning: unused variable 'edge_idx' [-Wunused-variable]
  113 |   int to = i.first, edge_idx = i.second;
      |                     ^~~~~~~~
oneway.cpp: In function 'void Solve()':
oneway.cpp:353:19: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  353 |  for(int i = 0; i < conditions.size(); i++)
      |                 ~~^~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...