답안 #288233

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
288233 2020-09-01T10:39:31 Z user202729 Simurgh (IOI17_simurgh) C++17
100 / 100
425 ms 7032 KB
// moreflags=grader.cpp
// 11
#include "simurgh.h"
#if not LOCAL
#define NDEBUG
#endif
#include<cassert>
#include<algorithm>

struct Dsu{
	std::vector<int> data;
	Dsu(int number){reset(number);}
	void reset(int number){data.assign(number, -1);}
	int root(int node){return data[node]>=0 ? data[node]=root(data[node]): node;}
	bool join(int first, int sec){
		first=root(first); sec=root(sec);
		if(first==sec) return false;
		data[first]=sec;
		return true;
	}
};

struct Edge{int node, index;};
std::vector<std::vector<Edge>> add;
std::vector<int> par, depth, parIndex;
std::vector<char> visited;

void work(int node, int curPar, int curDepth){
	par[node]=curPar; depth[node]=curDepth;
	assert(not visited[node]); visited[node]=true;
	for(auto [child, index]: add[node]) if(not visited[child]){
		parIndex[child]=index;
		work(child, node, curDepth+1);
	}
}

std::vector<int> find_roads(int n, std::vector<int> u, std::vector<int> v) {
	// construct a DFS tree
	add.resize(n);
	for(int index=0; index<(int)u.size(); ++index){
		auto const first=u[index], sec=v[index];
		add[first].push_back({sec, index});
		add[sec].push_back({first, index});
	}
	par.resize(n); depth.resize(n);
	visited.assign(n, false);
	parIndex.resize(n); parIndex[0]=-1;
	work(0, -1, 0);

	// compute value of that tree
	std::vector<int> tmp; tmp.reserve(n-1);
	for(int node=0; node<n; ++node)
		for(auto [other, index]: add[node]) if(depth[other]==depth[node]-1)
			tmp.push_back(index);
	int const treeValue=count_common_roads(tmp);

	// compute individual edges' values
	std::vector<int> value(u.size(), -1);
	for(int node=0; node<n; ++node){
		for(auto [other, backIndex]: add[node]) if(depth[other]<depth[node]-1){
			// back edge
			int& backValue=value[backIndex];
			assert(backValue==-1);

			for(int x=node; x!=other; x=par[x]){
				if(value[parIndex[x]]<0) goto anyUndefined;
			}
			continue;

anyUndefined:
			bool guessBackValue=true;
			backValue=0; // this is the guess.


			for(int x=node; x!=other; x=par[x]){
				auto const fixWrongBackValueGuess=[&]{
					for(int y=node; y!=x; y=par[y]){
						assert(value[parIndex[y]]==0); value[parIndex[y]]=1;
					}
				};
			
				int& curValue=value[parIndex[x]];
				if(guessBackValue or curValue<0){
					auto const iterator=std::find(begin(tmp), end(tmp), parIndex[x]);
					*iterator=backIndex;
					auto const v=count_common_roads(tmp)-treeValue; // == backValue-curValue
					*iterator=parIndex[x];

					switch(v){
						case 0:
							{
								if(curValue>=0){
									if(guessBackValue){
										assert(backValue==0); backValue=curValue;
										if(curValue==1) fixWrongBackValueGuess();

										guessBackValue=false;
									}else{
										assert(curValue==backValue);
									}
								}else{
									curValue=backValue;
								}
								break;
							}
						case -1:
							{
								assert(curValue!=0); curValue=1;
								assert(backValue==0);
								if(guessBackValue){
									guessBackValue=false; // already guessed correctly
								}
								break;
							}
						case 1:
							{
								assert(v==1);
								assert(curValue!=1);
								if(guessBackValue){
									assert(backValue==0); backValue=1;
									fixWrongBackValueGuess();
								}else assert(backValue==1);
								curValue=0; backValue=1; guessBackValue=false;
								break;

							}
						default:
							assert(false); __builtin_unreachable();
					}
				}
			}

			if(guessBackValue){
				assert(backValue==0);
				for(int x=node; x!=other; x=par[x])
					assert(value[parIndex[x]]==0);
				// also guessed correctly (there's no way the values of all those edges can be 1 at the same time)
			}
		}
	}

	// double check that tmp is the DFS tree
	for(int node=0; node<n; ++node)
		for(auto [other, index]: add[node]) if(depth[other]==depth[node]-1){
			assert(std::find(begin(tmp), end(tmp), index)!=tmp.end());
		}

	for(auto index: tmp)
		if(value[index]==-1) value[index]=1; // a bridge

	auto const treeEdges=std::move(tmp); tmp.clear();
	tmp.reserve(n-1);
	std::vector<std::pair<Dsu, std::vector<int>>> trees;
	trees.push_back({Dsu(n), {}});
	for(int index=0; index<(int)value.size(); ++index)
		if(value[index]<0){
			[&]{
				if(not trees.back().second.empty())
					trees.push_back({Dsu(n), {}});
				for(auto& [dsu, edges]: trees){
					if(dsu.join(u[index], v[index])){
						edges.push_back(index); return;
					}
				}
				assert(false); __builtin_unreachable();
			}();
		}
	while(not trees.empty() and trees.back().second.empty()) trees.pop_back();
	assert((int)trees.size()<=n-1);

	assert(tmp.empty());

	auto const process=[&](auto process, auto first, auto last, int count // -1: unknown
			)->int /* count */{
		if(count<0){
			Dsu dsu(n);
			std::for_each(first, last,[&](int index){
				assert(value[index]<0);
				dsu.join(u[index], v[index]);
			});
			if(first==last) return 0;

			assert(tmp.empty()); tmp.assign(first, last);

			int extra=0;
			for(auto index: treeEdges) if(dsu.join(u[index], v[index])){
				assert(value[index]>=0); extra+=value[index];
				tmp.push_back(index);
			}
			assert((int)tmp.size()==n-1);

			count=count_common_roads(tmp)-extra;
		}

#if LOCAL
		auto const store=tmp;
#endif
		tmp.clear();
		if(count==last-first)
			std::for_each(first, last,[&](int index){ value[index]=1; });
		else if(count==0)
			std::for_each(first, last,[&](int index){ value[index]=0; });
		else{
			assert(0<count); assert(count<last-first);
			auto const middle=first+((last-first)>>1);
			auto const count1=process(process, first, middle, -1);
			assert(count1<=count);
			process(process, middle, last, count-count1);
		}

		assert(count>=0);
		return count;
	};

	for(auto& [dsu, edges]: trees){
		process(process, begin(edges), end(edges), -1);
		edges.clear();
	}
	trees.clear();

	assert(tmp.empty());
	for(int index=0; index<(int)value.size(); ++index){
		assert(value[index]>=0);
		if(value[index]) tmp.push_back(index);
	}
	return tmp;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 256 KB correct
2 Correct 0 ms 256 KB correct
3 Correct 0 ms 256 KB correct
4 Correct 0 ms 256 KB correct
5 Correct 0 ms 256 KB correct
6 Correct 1 ms 256 KB correct
7 Correct 0 ms 256 KB correct
8 Correct 0 ms 256 KB correct
9 Correct 0 ms 256 KB correct
10 Correct 1 ms 256 KB correct
11 Correct 1 ms 256 KB correct
12 Correct 0 ms 256 KB correct
13 Correct 0 ms 256 KB correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 256 KB correct
2 Correct 0 ms 256 KB correct
3 Correct 0 ms 256 KB correct
4 Correct 0 ms 256 KB correct
5 Correct 0 ms 256 KB correct
6 Correct 1 ms 256 KB correct
7 Correct 0 ms 256 KB correct
8 Correct 0 ms 256 KB correct
9 Correct 0 ms 256 KB correct
10 Correct 1 ms 256 KB correct
11 Correct 1 ms 256 KB correct
12 Correct 0 ms 256 KB correct
13 Correct 0 ms 256 KB correct
14 Correct 2 ms 384 KB correct
15 Correct 2 ms 384 KB correct
16 Correct 2 ms 384 KB correct
17 Correct 2 ms 384 KB correct
18 Correct 1 ms 384 KB correct
19 Correct 2 ms 384 KB correct
20 Correct 2 ms 384 KB correct
21 Correct 2 ms 384 KB correct
22 Correct 1 ms 384 KB correct
23 Correct 1 ms 384 KB correct
24 Correct 1 ms 384 KB correct
25 Correct 1 ms 256 KB correct
26 Correct 1 ms 384 KB correct
27 Correct 1 ms 384 KB correct
28 Correct 1 ms 384 KB correct
29 Correct 1 ms 256 KB correct
30 Correct 1 ms 384 KB correct
31 Correct 1 ms 384 KB correct
32 Correct 1 ms 384 KB correct
33 Correct 1 ms 384 KB correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 256 KB correct
2 Correct 0 ms 256 KB correct
3 Correct 0 ms 256 KB correct
4 Correct 0 ms 256 KB correct
5 Correct 0 ms 256 KB correct
6 Correct 1 ms 256 KB correct
7 Correct 0 ms 256 KB correct
8 Correct 0 ms 256 KB correct
9 Correct 0 ms 256 KB correct
10 Correct 1 ms 256 KB correct
11 Correct 1 ms 256 KB correct
12 Correct 0 ms 256 KB correct
13 Correct 0 ms 256 KB correct
14 Correct 2 ms 384 KB correct
15 Correct 2 ms 384 KB correct
16 Correct 2 ms 384 KB correct
17 Correct 2 ms 384 KB correct
18 Correct 1 ms 384 KB correct
19 Correct 2 ms 384 KB correct
20 Correct 2 ms 384 KB correct
21 Correct 2 ms 384 KB correct
22 Correct 1 ms 384 KB correct
23 Correct 1 ms 384 KB correct
24 Correct 1 ms 384 KB correct
25 Correct 1 ms 256 KB correct
26 Correct 1 ms 384 KB correct
27 Correct 1 ms 384 KB correct
28 Correct 1 ms 384 KB correct
29 Correct 1 ms 256 KB correct
30 Correct 1 ms 384 KB correct
31 Correct 1 ms 384 KB correct
32 Correct 1 ms 384 KB correct
33 Correct 1 ms 384 KB correct
34 Correct 63 ms 1852 KB correct
35 Correct 61 ms 1912 KB correct
36 Correct 44 ms 1536 KB correct
37 Correct 8 ms 384 KB correct
38 Correct 64 ms 1792 KB correct
39 Correct 54 ms 1656 KB correct
40 Correct 48 ms 1528 KB correct
41 Correct 64 ms 1792 KB correct
42 Correct 64 ms 1792 KB correct
43 Correct 18 ms 1280 KB correct
44 Correct 15 ms 1024 KB correct
45 Correct 16 ms 1024 KB correct
46 Correct 12 ms 896 KB correct
47 Correct 6 ms 640 KB correct
48 Correct 2 ms 384 KB correct
49 Correct 4 ms 384 KB correct
50 Correct 6 ms 640 KB correct
51 Correct 17 ms 1024 KB correct
52 Correct 14 ms 1024 KB correct
53 Correct 13 ms 896 KB correct
54 Correct 19 ms 1228 KB correct
55 Correct 17 ms 1152 KB correct
56 Correct 18 ms 1104 KB correct
57 Correct 18 ms 1104 KB correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 256 KB correct
2 Correct 0 ms 256 KB correct
3 Correct 231 ms 4924 KB correct
4 Correct 412 ms 6836 KB correct
5 Correct 417 ms 6824 KB correct
6 Correct 423 ms 6752 KB correct
7 Correct 415 ms 6756 KB correct
8 Correct 424 ms 6904 KB correct
9 Correct 415 ms 6856 KB correct
10 Correct 417 ms 6776 KB correct
11 Correct 411 ms 7032 KB correct
12 Correct 425 ms 6776 KB correct
13 Correct 1 ms 256 KB correct
14 Correct 414 ms 6776 KB correct
15 Correct 412 ms 6908 KB correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 256 KB correct
2 Correct 0 ms 256 KB correct
3 Correct 0 ms 256 KB correct
4 Correct 0 ms 256 KB correct
5 Correct 0 ms 256 KB correct
6 Correct 1 ms 256 KB correct
7 Correct 0 ms 256 KB correct
8 Correct 0 ms 256 KB correct
9 Correct 0 ms 256 KB correct
10 Correct 1 ms 256 KB correct
11 Correct 1 ms 256 KB correct
12 Correct 0 ms 256 KB correct
13 Correct 0 ms 256 KB correct
14 Correct 2 ms 384 KB correct
15 Correct 2 ms 384 KB correct
16 Correct 2 ms 384 KB correct
17 Correct 2 ms 384 KB correct
18 Correct 1 ms 384 KB correct
19 Correct 2 ms 384 KB correct
20 Correct 2 ms 384 KB correct
21 Correct 2 ms 384 KB correct
22 Correct 1 ms 384 KB correct
23 Correct 1 ms 384 KB correct
24 Correct 1 ms 384 KB correct
25 Correct 1 ms 256 KB correct
26 Correct 1 ms 384 KB correct
27 Correct 1 ms 384 KB correct
28 Correct 1 ms 384 KB correct
29 Correct 1 ms 256 KB correct
30 Correct 1 ms 384 KB correct
31 Correct 1 ms 384 KB correct
32 Correct 1 ms 384 KB correct
33 Correct 1 ms 384 KB correct
34 Correct 63 ms 1852 KB correct
35 Correct 61 ms 1912 KB correct
36 Correct 44 ms 1536 KB correct
37 Correct 8 ms 384 KB correct
38 Correct 64 ms 1792 KB correct
39 Correct 54 ms 1656 KB correct
40 Correct 48 ms 1528 KB correct
41 Correct 64 ms 1792 KB correct
42 Correct 64 ms 1792 KB correct
43 Correct 18 ms 1280 KB correct
44 Correct 15 ms 1024 KB correct
45 Correct 16 ms 1024 KB correct
46 Correct 12 ms 896 KB correct
47 Correct 6 ms 640 KB correct
48 Correct 2 ms 384 KB correct
49 Correct 4 ms 384 KB correct
50 Correct 6 ms 640 KB correct
51 Correct 17 ms 1024 KB correct
52 Correct 14 ms 1024 KB correct
53 Correct 13 ms 896 KB correct
54 Correct 19 ms 1228 KB correct
55 Correct 17 ms 1152 KB correct
56 Correct 18 ms 1104 KB correct
57 Correct 18 ms 1104 KB correct
58 Correct 0 ms 256 KB correct
59 Correct 0 ms 256 KB correct
60 Correct 231 ms 4924 KB correct
61 Correct 412 ms 6836 KB correct
62 Correct 417 ms 6824 KB correct
63 Correct 423 ms 6752 KB correct
64 Correct 415 ms 6756 KB correct
65 Correct 424 ms 6904 KB correct
66 Correct 415 ms 6856 KB correct
67 Correct 417 ms 6776 KB correct
68 Correct 411 ms 7032 KB correct
69 Correct 425 ms 6776 KB correct
70 Correct 1 ms 256 KB correct
71 Correct 414 ms 6776 KB correct
72 Correct 412 ms 6908 KB correct
73 Correct 0 ms 256 KB correct
74 Correct 419 ms 7032 KB correct
75 Correct 409 ms 6648 KB correct
76 Correct 126 ms 2808 KB correct
77 Correct 414 ms 6780 KB correct
78 Correct 416 ms 6904 KB correct
79 Correct 414 ms 6776 KB correct
80 Correct 405 ms 6648 KB correct
81 Correct 333 ms 6136 KB correct
82 Correct 399 ms 6872 KB correct
83 Correct 206 ms 3960 KB correct
84 Correct 139 ms 4824 KB correct
85 Correct 113 ms 4344 KB correct
86 Correct 66 ms 2936 KB correct
87 Correct 43 ms 2424 KB correct
88 Correct 33 ms 1792 KB correct
89 Correct 34 ms 1692 KB correct
90 Correct 28 ms 1536 KB correct
91 Correct 12 ms 512 KB correct
92 Correct 7 ms 384 KB correct
93 Correct 113 ms 4472 KB correct
94 Correct 67 ms 2940 KB correct
95 Correct 61 ms 2936 KB correct
96 Correct 30 ms 1664 KB correct
97 Correct 34 ms 1784 KB correct
98 Correct 43 ms 2432 KB correct
99 Correct 37 ms 1784 KB correct
100 Correct 15 ms 640 KB correct
101 Correct 8 ms 384 KB correct
102 Correct 113 ms 3708 KB correct
103 Correct 114 ms 3740 KB correct
104 Correct 109 ms 3832 KB correct
105 Correct 112 ms 3588 KB correct