Google Code Jam.
This commit is contained in:
235
google_code_jam/2014/1A-B-code_jam.cpp
Normal file
235
google_code_jam/2014/1A-B-code_jam.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/* Check cf5-opt.vim defs.
|
||||
VIM: let g:lcppflags="-std=c++11 -O2 -pthread"
|
||||
VIM: let g:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM: let g:cppflags=g:Iboost.g:Itbb
|
||||
VIM: let g:ldflags=g:Lboost.g:Ltbb.g:tbbmalloc.g:tbbmproxy
|
||||
VIM: let g:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM: let g:argv=""
|
||||
*/
|
||||
|
||||
/*
|
||||
Problem B. Full Binary Tree
|
||||
This contest is open for practice. You can try every problem as many times as you like, though we won't keep track of which problems you solve. Read the Quick-Start Guide to get started.
|
||||
Small input
|
||||
9 points
|
||||
Judge's response for last submission: Correct.
|
||||
Large input
|
||||
21 points
|
||||
Judge's response for last submission: Correct.
|
||||
Problem
|
||||
|
||||
A tree is a connected graph with no cycles.
|
||||
|
||||
A rooted tree is a tree in which one special vertex is called the root. If there is an edge between X and Y in a rooted tree, we say that Y is a child of X if X is closer to the root than Y (in other words, the shortest path from the root to X is shorter than the shortest path from the root to Y).
|
||||
|
||||
A full binary tree is a rooted tree where every node has either exactly 2 children or 0 children.
|
||||
|
||||
You are given a tree G with N nodes (numbered from 1 to N). You are allowed to delete some of the nodes. When a node is deleted, the edges connected to the deleted node are also deleted. Your task is to delete as few nodes as possible so that the remaining nodes form a full binary tree for some choice of the root from the remaining nodes.
|
||||
Input
|
||||
|
||||
The first line of the input gives the number of test cases, T. T test cases follow. The first line of each test case contains a single integer N, the number of nodes in the tree. The following N-1 lines each one will contain two space-separated integers: Xi Yi, indicating that G contains an undirected edge between Xi and Yi.
|
||||
Output
|
||||
|
||||
For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the minimum number of nodes to delete from G to make a full binary tree.
|
||||
Limits
|
||||
|
||||
1 ≤ T ≤ 100.
|
||||
1 ≤ Xi, Yi ≤ N
|
||||
Each test case will form a valid connected tree.
|
||||
Small dataset
|
||||
|
||||
2 ≤ N ≤ 15.
|
||||
Large dataset
|
||||
|
||||
2 ≤ N ≤ 1000.
|
||||
Sample
|
||||
|
||||
Input
|
||||
|
||||
Output
|
||||
|
||||
|
||||
3
|
||||
3
|
||||
2 1
|
||||
1 3
|
||||
7
|
||||
4 5
|
||||
4 2
|
||||
1 2
|
||||
3 1
|
||||
6 4
|
||||
3 7
|
||||
4
|
||||
1 2
|
||||
2 3
|
||||
3 4
|
||||
|
||||
|
||||
|
||||
Case #1: 0
|
||||
Case #2: 2
|
||||
Case #3: 1
|
||||
|
||||
In the first case, G is already a full binary tree (if we consider node 1 as the root), so we don't need to do anything.
|
||||
|
||||
In the second case, we may delete nodes 3 and 7; then 2 can be the root of a full binary tree.
|
||||
|
||||
In the third case, we may delete node 1; then 3 will become the root of a full binary tree (we could also have deleted node 4; then we could have made 2 the root).
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef std::vector<std::pair<int,int>> vec;
|
||||
|
||||
typedef std::vector<std::vector<int>> ss;
|
||||
typedef std::vector<std::vector<int>> edges;
|
||||
typedef std::vector<std::pair<int,int>> vec;
|
||||
|
||||
int max_tree( ss& t, int i, int r )
|
||||
{
|
||||
if ( t[i].size() == 2 && r!=0 )
|
||||
return 1;
|
||||
|
||||
int m1 = 0;
|
||||
int m2 = 0;
|
||||
|
||||
for ( auto j: t[i] )
|
||||
{
|
||||
if ( j != r )
|
||||
{
|
||||
int mt = max_tree( t, j, i );
|
||||
if ( m1 < m2 )
|
||||
swap( m1, m2 );
|
||||
m2 = max(m2,mt);
|
||||
}
|
||||
}
|
||||
|
||||
return m1+m2+1;
|
||||
}
|
||||
|
||||
int check2(ss& t)
|
||||
{
|
||||
int n = 0;
|
||||
for ( auto& i: t )
|
||||
{
|
||||
if ( i.size() > 3 )
|
||||
n+=2;
|
||||
else if ( i.size() == 2 )
|
||||
n++;
|
||||
}
|
||||
if ( n == 1 )
|
||||
return 0;
|
||||
|
||||
int m = numeric_limits<int>::max();
|
||||
for ( int i = 0; i < t.size(); i++)
|
||||
{
|
||||
if ( t[i].size() == 1 )
|
||||
{
|
||||
ss t2 = t;
|
||||
|
||||
int v = t2[i][0];
|
||||
for ( int j = 0; j < t2[v].size(); ++j )
|
||||
if ( t2[v][j] == i )
|
||||
t2[v].erase(t2[v].begin()+j);
|
||||
t2[i].clear();
|
||||
|
||||
int m2 = check2(t2) +1;
|
||||
if ( m > m2 )
|
||||
m = m2;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
int solve_puzzle()
|
||||
{
|
||||
int n;
|
||||
cin >> n;
|
||||
ss t(n+1);
|
||||
vec s;
|
||||
for (int i = 0; i < n-1; i++ )
|
||||
{
|
||||
int v1, v2;
|
||||
cin >> v1 >> v2;
|
||||
s.push_back( make_pair(v1,v2) );
|
||||
if ( t.size() < v1 )
|
||||
t.resize(v1);
|
||||
if ( t.size() < v2 )
|
||||
t.resize(v2);
|
||||
t[v1].push_back(v2);
|
||||
t[v2].push_back(v1);
|
||||
}
|
||||
|
||||
if ( n == 2 )
|
||||
return 1;
|
||||
else if (n ==1 )
|
||||
return 0;
|
||||
|
||||
set<int> v;
|
||||
for ( int i = 0; i<t.size(); ++i )
|
||||
if ( t[i].size() == 2 || t[i].size() > 3 )
|
||||
v.insert(i);
|
||||
|
||||
if ( !v.size() )
|
||||
return 1;
|
||||
|
||||
int m = 0;
|
||||
for ( auto i : v )
|
||||
{
|
||||
int mt = max_tree( t, i, 0 );
|
||||
m = max(m,mt);
|
||||
}
|
||||
|
||||
// if ( check2(t) != (n-m) )
|
||||
// std::cout << "error" << std::endl;
|
||||
|
||||
return n-m;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
int puzzle_count;
|
||||
|
||||
std::cin >> puzzle_count;
|
||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
|
||||
for ( int i = 1; i <= puzzle_count; i++ )
|
||||
{
|
||||
std::cout << "Case #" << i << ": ";
|
||||
auto r = solve_puzzle();
|
||||
std::cout << r << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
Reference in New Issue
Block a user