Submission #302710

# Submission time Handle Problem Language Result Execution time Memory
302710 2020-09-19T04:39:47 Z user202729 Towns (IOI15_towns) C++17
61 / 100
27 ms 1024 KB
// moreflags=grader.cpp
#include "towns.h"
#include<algorithm>
#include<climits>
#include<map>
#include<vector>
#if not LOCAL
#define NDEBUG
#endif
#include<cassert>

int hubDistance(int number, int sub) {
	int const A=0; // * must be 0, relied upon by some code below
	std::vector<int> distanceA(number);
	for(int other=1; other<number; ++other)
		distanceA[other]=getDistance(A, other);

	int const B=int(std::max_element(begin(distanceA), end(distanceA))-distanceA.begin());
	std::vector<int> distanceB(number);
	distanceB[A]=distanceA[B];
	for(int other=1; other<number; ++other) if(other!=B)
		distanceB[other]=getDistance(B, other);
	auto const diameter=*std::max_element(begin(distanceB), end(distanceB));

	// distance from B -> [(distance from path AB, node index)...]
	std::map<int, std::vector<std::pair<int, int>>> groups;
	for(int node=0; node<number; ++node){
		auto const first=distanceA[node], sec=distanceB[node];
		assert((first+sec+distanceA[B])%2==0);
		groups[(sec+distanceA[B]-first)>>1].push_back({(first+sec-distanceA[B])>>1, node});
	}
	assert((groups.at(0)==std::vector<std::pair<int, int>>{{0, B}}));
	assert((groups.at(distanceA[B])==std::vector<std::pair<int, int>>{{0, A}}));
	// ^ technically have side effects (memory allocation and deallocation)

	int radius=INT_MAX, hubDistanceB; bool LRbalanced=false;
	{
		int sumLeftGroupSize=0; // exclude current group. Only count leaves
		int lastGroupSize, lastr, lastDistanceB;
		for(auto const& [distanceB, group]: groups){
			auto const r=std::max(distanceB, diameter-distanceB); // only correct for nodes on some diameter

			if(distanceB*2>=diameter){
				// node and lastNode are on some diameter
				// but the next node might not be
				// compare node and lastNode. One of them is the hub

				radius=std::min(lastr, r);
				bool const lastLRBalanced=
					std::max(sumLeftGroupSize-lastGroupSize, number-sumLeftGroupSize)
					<=number/2;
				bool const curLRBalanced=
					std::max(sumLeftGroupSize, number-sumLeftGroupSize-(int)group.size())
					<=number/2;
				assert(not (lastLRBalanced and curLRBalanced));

				if(radius==lastr){
					assert(not LRbalanced);
					hubDistanceB=lastDistanceB; LRbalanced=lastLRBalanced;
				}
				if(radius==r and curLRBalanced>=LRbalanced){ // if there are two, use the LRbalanced one
					hubDistanceB=distanceB; LRbalanced=curLRBalanced;
				}

				break;
			}
			lastGroupSize=(int)group.size(); lastr=r; lastDistanceB=distanceB;
			sumLeftGroupSize+=(int)group.size();
		}
	}

	assert(radius!=INT_MAX);
	if(sub<3){
		return radius;
	}

	if(not LRbalanced) // definitely not balanced
		return -radius;

	struct Dom{
		int node;
		int count;
		int pathDistance;
	}; // dominance component info
	Dom dom{-1, 0, -1};

	auto const sameDomComponent=[&](int node, int pathDistance){
		assert(node!=dom.node);
		return getDistance(node, dom.node)<dom.pathDistance+pathDistance;
	};

	for(auto const [pathDistance, node]: groups.at(hubDistanceB)){
		if(dom.count==0){
			dom={node, 1, pathDistance};
		}else{
			if(sameDomComponent(node, pathDistance)){
				++dom.count;
			}else{
				--dom.count;
				assert(dom.count>=0);
			}
		}
	}

	if(dom.count==0){
		// definitely balanced
		return radius;
	}

	// naive recount
	dom.count=1;
	for(auto const [pathDistance, node]: groups.at(hubDistanceB)) if(node!=dom.node){
		if(sameDomComponent(node, pathDistance))
			++dom.count;
	}

	return dom.count<=number/2 ? radius: -radius;
}

Compilation message

towns.cpp: In function 'int hubDistance(int, int)':
towns.cpp:40:36: warning: declaration of 'distanceB' shadows a previous local [-Wshadow]
   40 |   for(auto const& [distanceB, group]: groups){
      |                                    ^
towns.cpp:19:19: note: shadowed declaration is here
   19 |  std::vector<int> distanceB(number);
      |                   ^~~~~~~~~
towns.cpp:61:5: warning: 'lastr' may be used uninitialized in this function [-Wmaybe-uninitialized]
   61 |     if(radius==r and curLRBalanced>=LRbalanced){ // if there are two, use the LRbalanced one
      |     ^~
towns.cpp:50:31: warning: 'lastGroupSize' may be used uninitialized in this function [-Wmaybe-uninitialized]
   50 |      std::max(sumLeftGroupSize-lastGroupSize, number-sumLeftGroupSize)
      |               ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 20 ms 384 KB Output is correct
2 Correct 17 ms 512 KB Output is correct
3 Correct 0 ms 256 KB Output is correct
4 Correct 22 ms 384 KB Output is correct
5 Correct 22 ms 384 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 20 ms 408 KB Output is correct
2 Correct 16 ms 384 KB Output is correct
3 Correct 22 ms 504 KB Output is correct
4 Correct 22 ms 384 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 20 ms 384 KB Output is correct
2 Correct 23 ms 896 KB Output is correct
3 Correct 0 ms 256 KB Output is correct
4 Correct 22 ms 896 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 22 ms 384 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 18 ms 384 KB Output is correct
2 Correct 24 ms 1024 KB Output is correct
3 Correct 27 ms 896 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 384 KB Output isn't correct
2 Halted 0 ms 0 KB -