답안 #1035763

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1035763 2024-07-26T14:54:18 Z ALeonidou Simurgh (IOI17_simurgh) C++17
0 / 100
1 ms 348 KB
#include "simurgh.h"
#include <bits/stdc++.h>
using namespace std;

#define ll int
#define endl "\n"
#define sz(x) (ll)x.size()
#define F first
#define S second
#define pb push_back
#define ins insert

typedef vector <ll> vi;
typedef pair <ll,ll> ii;
typedef vector <ii> vii;

#define dbg(x) cout<<#x<<": "<<x<<endl;
#define dbg2(x,y) cout<<#x<<": "<<x<<" "<<#y<<": "<<y<<endl;
#define dbg3(x,y,z) cout<<#x<<": "<<x<<" "<<#y<<": "<<y<<" "<<#z<<": "<<z<<endl;

void printVct(vi &v){
	for (ll i =0; i<sz(v); i++){
		cout<<v[i]<<" ";
	}
	cout<<endl;
}

vector < vii > adj;

vi dp, h, vis;
vi bridges;
void dfs(ll u, ll height, ll p){
	// dbg(u);
	h[u] = height;
	dp[u] = height;
	vis[u] = 1;
	for (ll i =0; i<sz(adj[u]); i++){
		ll c = adj[u][i].F;
		if (c == p) continue;
		if (!vis[c]){
			dfs(c, height+1, u);
		}
		dp[u] = min(dp[u], dp[c]);
		if (dp[u] == dp[c]){
			// dbg2(u,c);
			bridges[adj[u][i].S] = 0;
		}
	}
}

vi par, siz;
ll fnd(ll x){
	if (x == par[x]) return x;
	return par[x] = fnd(par[x]);
}

void onion(ll a, ll b){
	a = fnd(a);
	b = fnd(b);
	if (a != b){
		if (siz[a] < siz[b]) swap(a,b);
		par[b] = a;
		siz[a] += siz[b];		
	}
}

//create span tree: O(N + M)
vi span_tree(ll n, ll m, ll processed_node, vi &u, vi &v, vi &royal_edges, vi &royal_edges_grid, ll on_edge = -1){
	vi q;
	//init DSU:
	par.resize(n);
	for (ll j =0; j<n; j++){
		par[j] = j;
	}
	siz.assign(n, 1);
	//connect on edge:
	if (on_edge != -1){
		onion(u[on_edge], v[on_edge]);
		q.pb(on_edge);
	}
	//connect royal edges:
	for (ll j =0; j<sz(royal_edges); j++){
		ll a = v[royal_edges[j]], b = u[royal_edges[j]];
		onion(a, b);
		q.pb(royal_edges[j]);
	}
	//rest of the edges without adding illegal edges
	for (ll j=0; j<m && sz(q) < n-1; j++){
		if (royal_edges_grid[j]) continue;
		ll a = v[j], b = u[j];
		if (a != processed_node && b != processed_node && fnd(a) != fnd(b)){
			onion(a,b);
			q.pb(j);
		}
	}
	// cout<<"q:";
	// printVct(q);
	//validate span tree:
	bool ok = true;
	for (ll j =1; j<n; j++){
		if (fnd(j) != fnd(j-1)){
			ok = false;
		}
	}
	if (!ok){
		q = vi();
	}
	return q;
}

vi find_roads(int n, vi u, vi v) {
	ll m = sz(u);
	adj.assign(n, vii());
	for (ll i =0; i<m; i++){
		adj[u[i]].pb(ii(v[i], i));
		adj[v[i]].pb(ii(u[i], i));
	}

	// step 1: find all bridges and mark them as royal
	bridges.assign(m, 1);
	h.resize(n);
	vis.assign(n, 0);
	dp.resize(n);
	dfs(0,0,-1);

	vi royal_edges, processed_edgs(m, 0), royal_edges_grid(m, 0);
	for (ll i =0; i<m; i++){
		if (bridges[i]){
			processed_edgs[i] = 1;
			royal_edges.pb(i);
			royal_edges_grid[i] = 1;
		}
	}

	// cout<<"royal:";
	// printVct(royal_edges);


	//step 2:
	for (ll i =0; i<n; i++){	//process nodes one by one
		// dbg(i);
		vi edges_to_process, q;
		for (ll j =0; j<sz(adj[i]); j++){
			ll id = adj[i][j].S;
			if (!processed_edgs[id]){
				edges_to_process.pb(id);
				processed_edgs[id] = 1;
			}
		}
		if (sz(edges_to_process) == 0) continue;
		
		// cout<<"edges_to_process: ";
		// printVct(edges_to_process);
		// return vi();

		//create span tree: O(N + M)
		q = span_tree(n,m,i,u,v,royal_edges,royal_edges_grid);
		// printVct(q);

		bool empty_is_valid = !q.empty();

		//Turn processed edges on/off
		if (sz(edges_to_process) == 1){
			ll val = count_common_roads(q);
			q = span_tree(n,m,i,u,v,royal_edges,royal_edges_grid,edges_to_process[0]);
			if (q.empty()) continue;
			ll x = count_common_roads(q);
			if (x > val){
				royal_edges.pb(edges_to_process[0]);
				royal_edges_grid[edges_to_process[0]] = 1;
			}
		}
		else{
			vii res; 	//res, id
			for (ll j = 0; j<sz(edges_to_process); j++){
				q = span_tree(n,m,i,u,v,royal_edges,royal_edges_grid,edges_to_process[j]);
				if (q.empty()) continue;
				// printVct(q);
				ll x = count_common_roads(q);
				res.pb(ii(x,edges_to_process[j]));
			}

			ll mini = res[0].F, maxi = res[0].S;
			for (ll j =0; j<sz(res); j++){
				mini = min(res[j].F, mini);
				maxi = max(res[j].F, maxi);
			}

			if (mini == maxi){
				for (ll j =0; j<sz(res); j++){
					royal_edges.pb(res[j].S);
					royal_edges_grid[res[j].S] = 1;
				}	
			}
			else{
				for (ll j =0; j<sz(res); j++){
					if (res[j].F == maxi){
						royal_edges.pb(res[j].S);
						royal_edges_grid[res[j].S] = 1;
					}
				}
			}
		}
	}

	// cout<<endl<<"ans:";
	// printVct(royal_edges);
	return royal_edges;
}

/*
5 7
0 1
0 2
0 3
1 2
1 3
2 3
3 4
0 1 5 6

5 5
0 1
1 2
1 3
2 3
3 4
0 1 2 4


4 6
0 1
0 2
0 3
1 2
1 3
2 3
0 1 5

*/

Compilation message

simurgh.cpp: In function 'vi find_roads(int, vi, vi)':
simurgh.cpp:160:8: warning: unused variable 'empty_is_valid' [-Wunused-variable]
  160 |   bool empty_is_valid = !q.empty();
      |        ^~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 344 KB WA in grader: NO
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 344 KB WA in grader: NO
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 344 KB WA in grader: NO
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 348 KB correct
2 Runtime error 0 ms 348 KB Execution killed with signal 11
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 344 KB WA in grader: NO
2 Halted 0 ms 0 KB -