結果
| 問題 |
No.912 赤黒木
|
| コンテスト | |
| ユーザー |
Jiro_tech15
|
| 提出日時 | 2019-10-18 23:15:24 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 536 ms / 3,000 ms |
| コード長 | 4,326 bytes |
| コンパイル時間 | 2,463 ms |
| コンパイル使用メモリ | 93,108 KB |
| 実行使用メモリ | 70,412 KB |
| 最終ジャッジ日時 | 2024-06-25 19:24:16 |
| 合計ジャッジ時間 | 13,976 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 30 |
ソースコード
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <iomanip>
#include <limits>
#include <list>
#include <queue>
#include <tuple>
#include <map>
#include <stack>
#include <set>
using namespace std;
#define MOD (long long int)(1e9+7)
#define ll long long int
#define rep(i,n) for(int i=0; i<(int)(n); i++)
#define reps(i,n) for(int i=1; i<=(int)(n); i++)
#define REP(i,n) for(int i=n-1; i>=0; i--)
#define REPS(i,n) for(int i=n; i>0; i--)
#define INF (int)(1123456789)
#define LINF (long long int)(112345678901234567)
#define chmax(a, b) a = (((a)<(b)) ? (b) : (a))
#define chmin(a, b) a = (((a)>(b)) ? (b) : (a))
#define all(v) v.begin(), v.end()
const int N = (int)3e5;
ll mpow(ll a, ll b){
if(b==0) return 1;
else if(b%2==0){ll memo = mpow(a,b/2); return memo*memo%MOD;}
else return mpow(a,b-1) * a % MOD;
}
ll lpow(ll a, ll b){
if(b==0) return 1;
else if(b%2==0){ll memo = lpow(a,b/2); return memo*memo;}
else return lpow(a,b-1) * a;
}
ll gcd(ll a, ll b){
if(b==0) return a;
else return gcd(b, a%b);
}
vector<ll> kaijo_memo;
ll kaijo(ll n){
if(kaijo_memo.size() > n) return kaijo_memo[n];
if(kaijo_memo.size() == 0) kaijo_memo.push_back(1);
while(kaijo_memo.size() <= n) kaijo_memo.push_back(kaijo_memo[kaijo_memo.size()-1] * kaijo_memo.size() % MOD);
return kaijo_memo[n];
}
vector<ll> gyaku_kaijo_memo;
ll gyaku_kaijo(ll n){
if(gyaku_kaijo_memo.size() > n) return gyaku_kaijo_memo[n];
if(gyaku_kaijo_memo.size() == 0) gyaku_kaijo_memo.push_back(1);
while(gyaku_kaijo_memo.size() <= n) gyaku_kaijo_memo.push_back(gyaku_kaijo_memo[gyaku_kaijo_memo.size()-1] * mpow(gyaku_kaijo_memo.size(), MOD-2) % MOD);
return gyaku_kaijo_memo[n];
}
ll nCr(ll n, ll r){
if(n == r) return 1;//0個の丸と-1個の棒みたいな時に時に効く?不安.
if(n < r || r < 0) return 0;
ll ret = 1;
ret *= kaijo(n); ret %= MOD;
ret *= gyaku_kaijo(r); ret %= MOD;
ret *= gyaku_kaijo(n-r); ret %= MOD;
return ret;
}
vector<ll> R[N],B[N];
bool checked[N],exist[N];
ll dp[N][3][2];
void saiki(int now){
if(checked[now]) return;
checked[now] = true;
vector<int> child;
rep(i,R[now].size()){
int next = R[now][i];
if(exist[next] && !checked[next]){
child.push_back(next);
}
}
rep(i,child.size()){
saiki(child[i]);
}
ll sum = 0;
ll most = -INF*(ll)10;
ll second = -INF*(ll)10;
ll twoMost = -INF*(ll)10;
int boo = B[now].size()%2;
rep(i,child.size()){
int next = child[i];
int b;
if(dp[next][0][0] < INF-30){
b = 0;
}else{
b = 1;
boo++;
boo%=2;
}
sum += dp[next][0][b] + b;
ll score = dp[next][0][b] - dp[next][1][1-b] + b*2-1;
if(most <= score){
second = most;
most = score;
}else if(second <= score){
second = score;
}
ll twoScore = dp[next][0][b] - dp[next][2][b];
chmax(twoMost, twoScore);
}
chmin(dp[now][0][boo],sum);
chmin(dp[now][1][1-boo],sum - most);
chmin(dp[now][2][boo],min(sum - most - second, sum - twoMost));
if(B[now].size()%2 == 1){
chmin(dp[now][2][boo],dp[now][1][1-boo]);
}
//cout<<now<<" "<<dp[now][0][boo]<<" "<<dp[now][1][1-boo]<<" "<<dp[now][2][boo]
//<<" "<<sum<<endl;
}
bool sakujo(int now){
if(checked[now]) return false;
checked[now] = true;
int count = 0;
rep(i,R[now].size()){
if(sakujo(R[now][i])){
count++;
}
}
if(count == 0){//削除対象かも?
if(B[now].size()%2 == 1){//葉である
exist[now] = true;
dp[now][0][1] = 0;
dp[now][1][0] = 0;
}else{//葉じゃない, 削除
exist[now] = false;
return false;
}
}else{
exist[now] = true;
}
return true;
}
int main(void){
ll n;cin>>n;
rep(i,n-1){
ll a,b;cin>>a>>b;a--;b--;
R[a].push_back(b);
R[b].push_back(a);
checked[i] = false;
}
rep(i,n-1){
ll c,d;cin>>c>>d;c--;d--;
B[c].push_back(d);
B[d].push_back(c);
}
rep(i,n){
rep(j,3){
rep(k,2){
dp[i][j][k] = INF;
}
}
}
sakujo(0);
rep(i,n){
rep(j,3){
rep(k,2){
//cout<<dp[i][j][k]<<" ";
}
}
//cout<<endl;
}
rep(i,n){
checked[i] = false;
}
saiki(0);
ll ans = min(dp[0][2][0], dp[0][2][1]) + n - 1;
cout<<ans<<endl;
return 0;
}
Jiro_tech15