Codeforces 1324 F. 최대 화이트 하위 트리 (나무 DP) / 의견

F. 최대 화이트 하위 트리
TEST2의 초 당 시간 제한
test256 메가 바이트 당 메모리 제한
입력 inputstandard
outputstandard 출력
당신은 n 개의 정점으로 구성된 트리를 제공하고 있습니다. 트리는 N-1 가장자리와 연결된 방향성 그래프이다. (정점 (V)이 흰색이면 정점 V 블랙이면 0 AV = 1)이 트리의 각 정점 V가 지정 색을 갖는다.

흰색의 수와 정점 V를 포함 주어진 트리의 일부 하위 트리를 선택하는 경우에 당신이 얻을 수있는 검은 색 정점의 수 사이의 최대의 차이점은 무엇입니까 : 각 정점 V에 대한 다음과 같은 문제를 해결해야? 트리의 서브 트리 주어진 트리의 연결 서브 그래프이다. 당신이 cntw 흰색 정점을 포함하는 하위 트리를 선택하고 검은 정점을 CNTB 경우 더 공식적으로, 당신은 cntw-CNTB을 극대화 할 수 있습니다.

입력
트리의 정점의 수 - 입력의 첫 번째 라인은 하나의 정수 n (2≤n≤2⋅105)을 포함한다.

입력의 두 번째 라인에 포함 된 N의 정수, A2가 A1, ..., (0≤ai≤1), i 번째의 정점의 색 인공 지능 여기서.

다음에 N-1 라인의 각각의 트리의 에지를 설명한다. 나는 두 정수 UI 및 VI 그것이 연결 정점 (1≤ui, vi≤n, UI ≠ VI)의 라벨에 의해 표시되는 가장자리.

주어진 가장자리 트리를 형성하는 것이 보장된다.

출력
인쇄 N 정수, RES2를 RES1, ... 집용 버텍스 I 일부를 포함하는 서브 트리의 흰색과 검은 색의 정점의 수 사이의 최대 가능한 차이 resn.


inputCopy
9
0 1 1 1 0 0 0 0 1
1 2
1 3
3 4
3 5
2-6
4-7
6-8
5-9
outputCopy
2 2 2 2 2 1 1 0 2
inputCopy
4
0 0 1 0
1 2
1 3
1 4를
outputCopy
0 -1 1 -1

문제의 의미 :
n 개의 점을 감안할 때, 색상의 각 지점 및 N-1면, 심지어 나무 / 루팅 해제 나무를 보장하기 위해 가장자리.
각 흰색 -cnt 검은 색 CNT하는 가장 큰 연결된 서브 그래프 지점을 찾고.

아이디어 :

  1. 클래식 나무 DP는 거물 내가 붕괴를 작성하는 지난 밤에 많은 변화 루트 야채이기 때문에이 템플릿의 문제라고.
  2. 개인 습관, u는 V 노드를 나타내는, 현재 노드를 나타냅니다.
  3. 서브 트리를 통과 할 때 루팅 해제 나무, 다음, 물론, 분명히 루트 노드를 리프 노드에 밀려 대답의 난 뿌리 하위 트리에 기여를 기록하기 위해 탄소 나노 튜브 어레이, 포인트 DFS를 선택하는 것입니다입니다 첫째 DFS 후 상태를 업데이트합니다.
  4. 상태 전이는 명백하다 : CNT [U] + = 최대 (0, CNT [V]). // 하위 트리 내에서 갱신
  5. DFS 내가 답변 어레이 (DP)를 기록하는 데 사용 루트, 이후 다시 변화하기 시작, DP 배열은 두 부분으로, 한 부분은 기여 DP [i]를 루트로 난 하위 트리이고, 다른 부분은 하위 트리 밖에 대답의 기여의 얼굴은, 우리가 계산해야하므로 때 하위 트리의 외부 부분의 루트를 변경합니다.
  6. 서브 트리를 횡단 할 때, CNT는 [V] CNT [U] 필요성 CNT에 기여하는 경우, [U] - = CNT [V]이므로 CNT V 루트 노드의 서브 트리에있을 때, [U]을 일시적으로 발현 CNT [V] + = 최대 (0, CNT [U]) 기부의 외부, 그리고이 시점에서의 상태 천이를 분명해진다. // 자식 트리 외부를 업데이트
  7. 그리고 탄소 나노 튜브 [V]와 CNT [U] 손해 배상, 때문에 우리는 배열의 탄소 나노 튜브와 하위 트리의 기여를 기록 할 경우에만 역 추적해야합니다.
  8. 세부 정보를 볼 수 ~ 코드
  9. 무엇이든 환영 메시지 교환의 개인 편지에 대한 불분명 한 이야기는 ~ 인 경우

코드 :

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}ll Inv(ll x,ll p){return qp(x,p-2,p);}
ll Cal(ll n,ll m,ll p){if (m>n) return 0;ll ans = 1;for(int i = 1; i <= m; ++i)
ans=ans*Inv(i,p)%p*(n-i+1)%p;return ans%p;}

const int manx=2e5+5;

ll col[manx],vis[manx],dp[manx],cnt[manx];
vector<ll>g[manx];
ll cnt1=0,cnt2=0,n,top;

void dfs(ll u){
    vis[u]=1;
    cnt[u]=(col[u]==1?1:-1);
    for(auto v: g[u]){
        if(vis[v]) continue;
        dfs(v);
        if(cnt[v]>0) cnt[u]+=cnt[v];
    }
}
void dfs1(ll u){
    dp[u]=cnt[u]; vis[u]=1;
    for(auto v: g[u]){
        if(vis[v]) continue;
        if(cnt[v]>0) cnt[u]-=cnt[v];
        if(cnt[u]>0) cnt[v]+=cnt[u];
        dfs1(v);
        if(cnt[u]>0) cnt[v]-=cnt[u];
        if(cnt[v]>0) cnt[u]+=cnt[v];
    }
}
int main(){

    n=read();
    for(int i=1;i<=n;i++) col[i]=read(),f[i]=i;
    for(int i=1;i<n;i++){
        ll u=read(),v=read();
        g[u].pb(v),g[v].pb(u);
    }
    dfs(1);
    for(int i=1;i<=n;i++) vis[i]=0;
    dfs1(1);
    for(int i=1;i<=n;i++)
        printf("%lld ",dp[i]);
    return 0;
}
게시 76 개 원래 기사 · 원 찬양 43 ·은 20000 +를 볼

추천

출처blog.csdn.net/JiangHxin/article/details/104834074