codeforces1156D 0-1-Tree Root change dp

Topic Portal

Meaning of the questions:

  Given an n-point edge weight of the tree is 0 or 1, a valid path (x, y) (x ≠ y) is satisfied, go from x y, once through the right side of an edge, it is not then through the right side to side 0, find the number of edges satisfying the condition?

Thinking: set $ f [u] $ is the root of 1, the bottom-end node $ U $ is the number of valid paths 1, $ g [u] $ 1 representative of the root, the bottom-up $ v $ end node is the number of legitimate paths 0, this can be solved by simple dfs again.

  Then set $ NF [u] $ and $ ng [u] represents the number of two kinds of legal $ u is the root path, commutation DFS roots, the root change in the process:

  If an edge of one side is 0, then:

    $ Ng [st.to] = ng [u] $, $ nf [st.to] = f [st.to] $. This equation is also well understood, the white side of the path will not change, all black transferred from the parent node from top to bottom over the edge to where the path is illegal.

  If a 1 is a side edge, then:

    $ Ng [st.to] = g [st.to] $, $ nf [st.to] = nf [u] -g [st.to] + ng [u] $, white edge only come up from the bottom of the. Subtracting the black side to side to the current position of the parent node black and white sides of the edges formed by connecting the parent node plus the white side, with side edges formed by black.

#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
const int maxn=200010;
ll rd()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int T;
struct edge{
    int to,w;
};
vector<edge>ve[maxn];
int f[maxn],g[maxn],nf[maxn],ng[maxn];
int n,m;
ll ans;
void dfs_1(int u,int fa){
    for(auto &st:ve[u]){
        if(st.to==fa)continue;
        dfs_1(st.to,u);
        if(st.w==0){
            g[u]+=g[st.to]+1;
        }else{
            f[u]+=f[st.to]+1+g[st.to];
        }
    }
}
void dfs_2(int u,int fa){
    ans+=nf[u]+ng[u];
    for(auto &st:ve[u]){
        if(st.to==fa)continue;
        if(st.w==0){
            ng[st.to]=ng[u];
            nf[st.to]=f[st.to];
        }else{
            ng[st.to]=g[st.to];
            nf[st.to]=nf[u]-g[st.to]+ng[u];
        }
        dfs_2(st.to,u);
    }
}
int main(){
    cin>>n;
    rep(i,1,n-1){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        ve[u].pb({v,w});
        ve[v].pb({u,w});
    }
    dfs_1(1,0);
    nf[1]=f[1],ng[1]=g[1];
    dfs_2(1,0);
    cout<<ans<<endl;
} 
View Code

 

Guess you like

Origin www.cnblogs.com/mountaink/p/11597906.html