"Today's Toutiao Cup" The First Hubei University Programming Contest - D. Who killed Cock Robin (tree-shaped DP/multiplication principle)

"Today's Toutiao Cup" The First Hubei University Programming Contest - D. Who killed Cock Robin (tree-shaped DP/multiplication principle)

Topic link: D. Who killed Cock Robin

meaning of the title

​ Give you a tree (n points, n-1 edges) and let you find the number of connected graph combinations in it, for example, there is a degenerate tree 1->2->3->4, now the connected graph combination here The numbers are (1),(2),(3),(4),(1-2),(2-3),(3-4),(1-2-3),(2-3-4 ), (1-2-3-4) , 10.


ideas

这里先定义每个节点的权值为以该节点为根的子图的种类的数目。那么对于所有叶子节点权值都为1,而对于节点1,需要遍历他的每一个子树,并且子树间的权值需要相乘才得到节点1的权值。请看下图就可以发现它们之间的联系了。每一个now[i]存的都是包括i点在内,不包括父节点,最大数量的连通图。这里的DP其实也用到了乘法原理。

code

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)(j);i <= (int)(k);i ++)
#define per(i,j,k) for(int i = (int)(j);i >= (int)(k);i --)
#define mmm(a,b)   memset(a,b,sizeof(a))
#define pb push_back

typedef long long ll;
const int INF  = (int)0x3f3f3f3f;
const int MAXN = (int)2e5+7;
const ll  MOD  = (ll)1e7+7;

ll now[MAXN];
ll ans;

vector<int> vp[MAXN];

ll dfs(int x){
    now[x] = 1;
    ll res = 1;
    rep(i,0,vp[x].size()-1){
        int t = vp[x][i];
        if (now[t]) continue;
        res = (res*(dfs(t)+1))%MOD;
    }
    now[x] = res;
    return res;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int N;
    cin >> N;
    rep(i,1,N-1){
        int x,y;
        cin >> x >> y;
        vp[x].pb(y);
        vp[y].pb(x);
    }

    dfs(1);

    rep(i,1,N){
        ans = (ans+now[i])%MOD;
    }
    cout << ans << endl;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324887085&siteId=291194637