Submission #283922

#TimeUsernameProblemLanguageResultExecution timeMemory
283922erd1Simurgh (IOI17_simurgh)C++14
100 / 100
293 ms7080 KiB
#include "simurgh.h"

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
typedef pair<int, int> pii;
typedef long long lld;
typedef long double ld;

template<typename Iter>
ostream& outIt(ostream& out, Iter b, Iter e){
	for(Iter i = b; i != e; ++i)
		out << (i == b?"":" ") << *i;
	return out;
}
template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> p){
	return out << '(' << p.ff << ", " << p.ss << ')';
}
template<typename T>
ostream& operator<<(ostream& out, vector<T> v){
	return outIt(out << '[', all(v)) << ']';
}


vector<vector<pii>> G;
vector<bool> asked, ans;
vector<int> te, es, dep, par, pe;
vector<pii> Edges;
//int c = 0;
int dfs(int i, int d = 1){
	//cout << i << " " << d << " " << par[i] << endl;
	//if(c++>100)exit(-1);
	dep[i] = d;
	int minup = d;
	for(auto x : G[i]){
		if(x.ss == pe[i])continue;
		if(dep[x.ff]){
			//cout << "counter" << x << endl;
			minup = min(minup, dep[x.ff]);
			continue;
		}
		es.pb(x.ss);
		te[x.ss] = es.size();
		pe[x.ff] = x.ss; par[x.ff] = i;
		minup = min(minup, dfs(x.ff, d + 1));
	}
	if(!i)return 0;
	//cout << i << minup << endl;
	if(minup == d){
		ans[pe[i]] = true;
		asked[pe[i]] = true;
	}
	return minup;
}

int asking(int tree, int nontree){
	//cout << "ask " << tree << " " << nontree << endl;
	swap(es[te[tree]-1], nontree);
	int ansx = count_common_roads(es);
	swap(es[te[tree]-1], nontree);
	//cout << ansx << endl;
	return ansx;
}

vector<int> dsu;
int root(int i){ return i == dsu[i] ? i : (dsu[i] = root(dsu[i])); }
inline bool join(int i, int j){ i = root(i), j = root(j); if(i == j)return false; dsu[i] = j; return true; }

int ask2(vector<int>& v){
	//cout << v << es << endl;
	iota(all(dsu), 0);
	int mm = v.size(), cnt = 0;
	for(auto i: v)assert(join(Edges[i].ff, Edges[i].ss));
	//cout << "gh" << endl;
	for(auto i: es)
		if(join(Edges[i].ff, Edges[i].ss))
			cnt += ans[i], v.pb(i);
	int ret = count_common_roads(v);
	v.resize(mm);
	return ret - cnt;
}

void process(int k){
	vector<int> gt, a;
	for(auto x: G[k])
		if(!asked[x.ss])gt.pb(x.ss);
	if(gt.size() == 0)return;
	int deg = ask2(gt);
	//cout << "process" << k << endl;
	//for(auto i: gt)cout << Edges[i]; cout << endl;
	//cout << deg << endl;
	for(int i = 0; i < deg; i++){
		int l = 0, r = gt.size();
		while(r-l > 1){
			a.resize(0);
			for(int j = 0; j < (l+r>>1); j++)a.pb(gt[j]);
			(ask2(a) <= i?l:r) = l+r>>1;
		}
		ans[gt[l]] = true;
	}
	for(auto i: gt)asked[i] = true;
	//cout << asked << endl << ans << endl << endl;
}

vector<int> find_roads(int n, vector<int> u, vector<int> v) {
	int m = u.size();
	te.resize(m); asked.resize(m); ans.resize(m); pe.resize(n); par.resize(n); dep.resize(n); pe[0] = -1; dsu.resize(n);
	G.resize(n);
	for(int i = 0; i < m; i++)Edges.pb({u[i], v[i]});
	for(int i = 0; i < m; i++)G[u[i]].pb({v[i], i}), G[v[i]].pb({u[i], i});
	dfs(0);
	int tans = count_common_roads(es);
	//cout << tans << endl;
	//cout << asked << endl;
	//cout << te << es << dep << par << endl;
	for(int i = 0; i < m; i++) if(dep[u[i]] < dep[v[i]])swap(u[i], v[i]);
	for(int i = 0; i < m; i++)
		if(!te[i]){
			//cout << i << endl;
			int tt = -1, go = false;
			for(int c = u[i]; c != v[i]; c = par[c]){
				if(asked[pe[c]])tt = pe[c];
				else go = true;
			}
			if(!go)continue;

			if(tt != -1){
				{
					int cans = asking(tt, i);
					if(cans == tans)ans[i] = ans[tt];
					else if(cans < tans)ans[i] = false, assert(ans[tt] == true);
					else if(cans > tans)ans[i] = true, assert(ans[tt] == false);
					asked[i] = true;
				}
				for(int c = u[i]; c != v[i]; c = par[c])
					if(!asked[pe[c]]){
						int cans = asking(pe[c], i);
						if(cans == tans)ans[pe[c]] = ans[i];
						else if(cans < tans)ans[pe[c]] = true;
						else if(cans > tans)ans[i] = true;
						asked[pe[c]] = true;
					}
			}else{
				for(int c = u[i]; c != v[i]; c = par[c])
					if(!asked[pe[c]]){
						int cans = asking(pe[c], i);
						if(cans < tans)ans[pe[c]] = true;
						else if(cans > tans)ans[i] = true;
						if(cans != tans)asked[pe[c]] = asked[i] = true;
					}
				asked[i] = true;
				for(int c = u[i]; c != v[i]; c = par[c])
					if(!asked[pe[c]]) ans[pe[c]] = ans[i], asked[pe[c]] = true;
			}
		}
	//cout << asked << endl << ans << endl;
	for(int i = 0; i < n; i++)process(i);

	//cout << asked << endl << ans << endl;
	vector<int> ret;
	for(int i = 0; i < m; i++){
		assert(asked[i]);
		if(ans[i])ret.pb(i);
	}
	//assert(ret.size() == n-1);
	return ret;
}

Compilation message (stderr)

simurgh.cpp: In function 'void process(int)':
simurgh.cpp:100:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  100 |    for(int j = 0; j < (l+r>>1); j++)a.pb(gt[j]);
      |                        ~^~
simurgh.cpp:101:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  101 |    (ask2(a) <= i?l:r) = l+r>>1;
      |                         ~^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...