湖北省大学程序设计竞赛(网络同步赛) D. Who killed Cock Robin

 
  

链接:https://www.nowcoder.com/acm/contest/104/C来源:牛客网

题目描述

Who killed Cock Robin?

I, said the Sparrow, With my bow and arrow,I killed Cock Robin.

Who saw him die?

I, said the Fly.With my little eye,I saw him die.

Who caught his blood?

I, said the Fish,With my little dish,I caught his blood.

Who'll make his shroud?

I, said the Beetle,With my thread and needle,I'll make the shroud.    

.........

All the birds of the air

Fell a-sighing and a-sobbing.

When they heard the bell toll.

For poor Cock Robin.

March 26, 2018

Sparrows are a kind of gregarious animals,sometimes the relationship between them can be represented by a tree.

The Sparrow is for trial, at next bird assizes,we should select a connected subgraph from the whole tree of sparrows as trial objects.

Because the relationship between sparrows is too complex, so we want to leave this problem to you. And your task is to calculate how many different ways can we select a connected subgraph from the whole tree.

输入描述:

 
   

The first line has a number n to indicate the number of sparrows.

The next n-1 row has two numbers x and y per row, which means there is an undirected edge between x and y.

输出描述:

 
   

The output is only one integer, the answer module 10000007 (107+7) in a line

题目意思

给你一个无根树,问你有多少个不同的连通子树。

个人思路

当然是D了个P啦,把无根树变有根树,找个度为1的点开始DFS。

然后,每次返回当前节点子树能组成多少个不同的子树。

ans+=每次DFS的返回值。

关键在于求当前节点能组成多少个不同的子树!

这时候就要感谢我的队友,感谢他证明了愚蠢的我,不然会被卡很久滴。

比如上图(忽略劣质画工),用W数组表示带上这个节点会产生多少个子树,对于节点5,它是个叶子,只会产生一个子树,w[5]=1,同理,w[6]=1,w[4]=1,w[7]=1。现在到了节点3了,节点3有两个儿子5和6,怎么求呢,队友提醒加个空集,即对于子节点的取法可以不取它,用空表示,所以,w[i]=w[i]*(w[i的儿子]+1),这个DP就D出来啦~

注意一下,虽然最后要对1e7+7取模,但是,中间1e5*1e5会爆了int,所以,以后不要在乎那些小的空间啦。

最后,附上美丽的代码。

#include<bits/stdc++.h>
using namespace std;
const int ha = 10000007;
vector<int> g[200010];
bool vis[200010];
long long w[200010];
long long ans=0;
int du[200010];
int n;
void read(){
    int j,k;
    vis[1]=true;    w[1]=1;
    memset(du,0,sizeof(du));
    for (int i=1;i<n;++i){
        vis[i+1]=true;  w[i+1]=1;
        scanf("%d%d",&j,&k);
        g[j].push_back(k);
        g[k].push_back(j);
        du[j]++;    du[k]++;
    }
}
void dfs(int u){
    vis[u]=false;
    w[u]=1;
    vector<int>::iterator it;
    int a=1;
    for (it=g[u].begin();it!=g[u].end();++it){
        int k=*it;
        if (vis[k]){
            dfs(k);
            w[u]=(w[u]*(w[k]+1))%ha;
        }
    }
    ans+=w[u];
    ans%=ha;
    return ;
}
void solve(){
    for (int i=1;i<=n;++i){
        if (du[i]==1&&vis[i]){
            dfs(i);
        }
    }
    printf("%d\n",ans);
    return ;
}
int main(){
    scanf("%d",&n);
    read();
    solve();
    return 0;
}


猜你喜欢

转载自blog.csdn.net/AC_hunter/article/details/80041350