"Matching tree tree dp"

<> Yes

<First update>


<Text>

Matching trees

Description

Managing work today are lazy lazy. Staring out the window in a daze of gentle discovery, we happened to see a tree of n nodes through the window. A tree of n nodes comprising n-1 edges, and the n nodes are Unicom. I.e., the distance between two trees number of edges in the shortest path between two points included.
Managing whim want to choose a set of edges trees (can be empty) deleted so that the maximum match after deleting the rest of the figure is unique. Managing want to know the number to meet the conditions of the edge set. Set the number of edges satisfy the condition may be a lot, please modulo 998,244,353.
A matching graph is a subset of graph edges, the condition is not dependent on any two sides of the same node. All matching figure, a maximum number of edges is the maximum matching of the matching graph.

Input Format

A first line integer n.
Next, n-1 lines each two integers ai, bi, represents between an edge node ai and bi.
For ≤ 3000 ≤ n-2 40%
2 ≤ ≤ n-300000 for 100%

Output Format

Outputs an integer number of edges satisfy the condition set are asking for modulo 998 244 353

Sample Input

4 
1 2 
1 3 
1 4

Sample Output

4

Resolve

First convert the meaning of problems: a maximum matching in fact the only point is equivalent to the figure of either isolated or part of the biggest matches.

The necessity of this condition is obvious, that is to say, the only maximum matching, the conditions must be met. Similarly, we can also prove that the conditions are adequate: the reductio ad absurdum, suppose there is a point, it is neither isolated nor maximum matching, and the biggest single match this figure. We discuss two cases:

\ (1 \) at this point even to the point belongs to the biggest matches, the biggest contradiction with the uniqueness of the match
\ (2 \) even to the point of this point does not belong to the biggest matches, the maximum and the maximum match contradictions

So these two propositions are equivalent.

那么我们就可以考虑树形\(dp\)计数。设\(f1[x]\)代表节点\(x\)等待他的父节点与他匹配,子树\(x\)的方案数,\(f2[x]\)代表节点\(x\)孤立,子树\(x\)的方案数,\(f3[x]\)代表节点\(x\)已经与某一个儿子匹配,子树的\(x\)的方案数。然后列状态转移方程:

\[f1_{x}=\prod_{y\in son(x)}(f2_y+2f3_y)\\f2_x=\prod_{y\in son(x)}(f2_y+f3_y)\\f3_x=\sum_{y\in son(x)} \left ( \frac{\prod_{z\in son(x),z\not= y}(f2_z+2f3_z)}{f2_y+2f3_y}*f1_y \right )\]

为什么\(f3\)都要乘\(2\),是因为当前节点\(x\)\(f3\)这种完成状态之间的边可连可不连。关于第三个状态转移方程,其含义为选一个点\(y\)\(f1\)状态与其匹配,剩下的同理随便选。

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
const int N = 300020;
const long long Mod = 998244353;
struct edge { int ver,next; } e[N*2];
int n,t,Head[N];
long long f1[N],f2[N],f3[N];
// f1 means which node is waiting mathcing
// f2 means which node is isolated
// f3 means which node has already matched
inline void insert(int x,int y)
{
    e[++t] = (edge){y,Head[x]} , Head[x] = t;
    e[++t] = (edge){x,Head[y]} , Head[y] = t;
}
inline void input(void)
{
    scanf("%d",&n);
    for ( int i = 1; i < n; i++ )
    {
        int x,y;
        scanf("%d%d",&x,&y);
        insert( x , y );
    }
}
inline long long power(long long a,long long b)
{
    long long res = 1;
    while ( b )
    {
        if ( 1 & b ) res = res * a % Mod;
        a = a * a % Mod , b >>= 1;
    }
    return res;
}
inline void mul(long long &a,long long b) { a = a * b % Mod; }
inline void add(long long &a,long long b) { a += b; if ( a >= Mod ) a -= Mod; }
inline void dp(int x,int f)
{
    f1[x] = f2[x] = 1LL;
    long long val = 1LL;
    for ( int i = Head[x]; i; i = e[i].next )
    {
        int y = e[i].ver;
        if ( y == f ) continue;
        dp( y , x );
        mul( f1[x] , ( f2[y] + 2 * f3[y] ) % Mod );
        mul( f2[x] , ( f2[y] + f3[y] ) % Mod );
        mul( val , ( f2[y] + 2 * f3[y] ) % Mod );
    }
    for ( int i = Head[x]; i; i = e[i].next )
    {
        int y = e[i].ver;
        if ( y == f ) continue;
        long long inv = power( f2[y] + 2 * f3[y] , Mod-2 );
        long long sum = val;
        mul( sum , inv ) , mul( sum , f1[y] );
        add( f3[x] , sum );
    }
}
int main(void)
{
    input();
    dp( 1 , 0 );
    printf("%lld\n", ( f2[1] + f3[1] ) % Mod );
    return 0;
}

<后记>

Guess you like

Origin www.cnblogs.com/Parsnip/p/11203680.html