APC001 E - Antennas on Tree
問題
問題概要
- 木が与えられる。
- 木のノードを アンテナを 個設置する。
- すべてのノードに対して、すべての選択したノードからの距離を数えて、これをベクトルとする
- このベクトルが同じにならないようにすることができる最小のを求める。
考察
- アンテナを置いてBFS的に距離を数えていくと、分岐した先で必ず一つはアンテナをおかなければならない
- 次数が2なノード(一直線なグラフ)を挿入しても全く影響しないことがわかるので、次数が2なノードは無視して考える。(もしすべての次数が2以下の場合は端にアンテナを一つおけばよい)
- このようなうにの中心(2番)にアンテナを置くのは無意味 2番を中心に、1,3,4のうちどれを置くか考える。
- 葉のうち、すべてを置く必要はなく、一つだけおかなくても良い。(なので今回はになる)
つまり、以下の処理をすれば行けそう。
- rootノードは次数3以上のものを設定する(ここにはアンテナはおかない。ない場合は1を出力して終了)
- DFSで木を見ていく
- 葉の数-1をroot側に伝えていく。
ソースコード
#include <iostream> #include <queue> #include <map> #include <list> #include <vector> #include <string> #include <stack> #include <limits> #include <climits> #include <cassert> #include <fstream> #include <cstring> #include <cmath> #include <bitset> #include <iomanip> #include <algorithm> #include <functional> #include <cstdio> #include <ciso646> #include <set> #include <array> #include <unordered_map> using namespace std; #define FOR(i,a,b) for (int i=(a);i<(b);i++) #define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--) #define REP(i,n) for (int i=0;i<(n);i++) #define RREP(i,n) for (int i=(n)-1;i>=0;i--) #define inf 0x3f3f3f3f #define PB push_back #define MP make_pair #define ALL(a) (a).begin(),(a).end() #define SET(a,c) memset(a,c,sizeof a) #define CLR(a) memset(a,0,sizeof a) #define VS vector<string> #define VI vector<ll> #define DEBUG(x) cout<<#x<<": "<<x<<endl #define MIN(a,b) (a>b?b:a) #define MAX(a,b) (a>b?a:b) #define pi 2*acos(0.0) #define INFILE() freopen("in0.txt","r",stdin) #define OUTFILE()freopen("out0.txt","w",stdout) #define ll long long #define ull unsigned long long #define pii pair<ll,ll> #define pcc pair<char,char> #define pic pair<ll,char> #define pci pair<char,ll> #define eps 1e-14 #define FST first #define SEC second #define SETUP cin.tie(0), ios::sync_with_stdio(false), cout << setprecision(15) namespace { struct input_returnner { ll N; input_returnner(ll N_ = 0) :N(N_) {} template<typename T> operator vector<T>() const { vector<T> res(N); for (auto &a : res) cin >> a; return std::move(res); } template<typename T> operator T() const { T res; cin >> res; return res; } template<typename T> T operator - (T right) { return T(input_returnner()) - right; } template<typename T> T operator + (T right) { return T(input_returnner()) + right; } template<typename T> T operator * (T right) { return T(input_returnner()) * right; } template<typename T> T operator / (T right) { return T(input_returnner()) / right; } template<typename T> T operator << (T right) { return T(input_returnner()) << right; } template<typename T> T operator >> (T right) { return T(input_returnner()) >> right; } }; template<typename T> input_returnner in() { return in<T>(); } input_returnner in() { return input_returnner(); } input_returnner in(ll N) { return std::move(input_returnner(N)); } } const ll MOD = 1e9 + 7; struct ModInt { ll v = 0; ModInt() {} template<class T> ModInt(const T& right) { v = right; if (v >= 0) v %= MOD; else v += ((-v) / MOD + 1)*MOD; v %= MOD; } void operator = (const ModInt& right) { v = right.v; } template<class T> void operator = (const T& right) { v = right; if (v >= 0) v %= MOD; else v = v += ((-v) / MOD + 1)*MOD; v %= MOD; } ModInt operator + (const ModInt& right) { return (v + right.v) % MOD; } ModInt operator - (const ModInt& right) { return (MOD - (v - right.v)); } ModInt operator * (const ModInt& right) { return (v * right.v) % MOD; } ModInt operator / (const ModInt& right) { return v / right.v; } void operator += (const ModInt& right) { v = (v + right.v) % MOD; } void operator -= (const ModInt& right) { v = (MOD - (v - right.v)); } void operator *= (const ModInt& right) { v = (v* right.v) % MOD; } void operator /= (const ModInt& right) { v = v / right.v; } bool operator == (const ModInt& right) { return v == right.v; } }; ostream& operator << (ostream& os, const ModInt& value) { os << value.v; return os; } string YN[] = { "No", "Yes" }; void solve(); /// ---template--- #define int ll int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a; } signed main() { SETUP; solve(); #ifdef _DEBUG system("pause"); #endif return 0; } vector<int> A; vector<vector<int> > G; int DFS(int node, int prev) { bool isZeroCheck = false; int res = 0; for (auto &to : G[node]) if(to != prev){ const int score = DFS(to, node); if (score == 0) { if (not isZeroCheck) isZeroCheck = true; else res++; } else res += score; } return res; } void solve() { int N; cin >> N; G.resize(N); REP(i, N-1) { int a, b; cin >> a >> b; G[a].push_back(b); G[b].push_back(a); } bool isThree = false; REP(i, G.size()) if (2 < G[i].size()) { cout << DFS(i, -1) << endl; return; } cout << 1 << endl; }