luogu 2509. 森林大礼包

2509. 森林大礼包

★   输入文件:three_squirrels.in   输出文件:three_squirrels.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】

 

   有一天紫萱学姐心情不好,学长就买了一个自己最喜欢吃的森林大礼包送给学姐,因为反正最后都是自己吃。

   森林大礼包里一共可能有n种包装袋,编号为0~n-1,0号包装袋里有一颗坚果,所有1~n-1号包装袋里都装着若干包其他包装袋,但是不会出现一个包装袋的某个子包装袋里包含这这个包装袋本身的灵异现象。

  最终森林大礼包里也会装着若干个包装袋,为了方便表示,我们将森林大礼包视为n号包装袋。请你帮助紫萱学姐计算这个大礼包里一共有多少颗坚果,由于答案可能很大,输出这个数对10^9+7取余的结果。

 

【输入格式】

 

  输入数据第一行为一个整数n,意义如题目所示。

  接下来n行,第i行一个整数ki,代表i号包装袋中含有ki个其他包装袋,接下来ki个整数aij代表这ki个包装袋的编号。

 

【输出格式】

 

  一个整数,意义如题目所示。

 

【样例输入】

7
1 0
2 0 1
2 1 2
2 2 3
2 3 4
2 4 5
2 5 6

【样例输出】

21

【提示】

 

样例中7个包装袋中的坚果数组成了一个斐波那契数列。

对于40%的数据,n≤10。

对于70%的数据,aij<i。

对于100%的数据,n≤100000,0<ki≤10,0≤aij<n且≠i,对于1≤x<y≤ki,aix可能与aiy相等,即一个包装袋内可能装有多个相同编号的包装袋。

 

【来源】

mzx

这题用邻接表被卡了(555)

返乡topsort 从里向外拓扑,也就是该层为内层之和

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=1e5+20;
const int MOD=1e9+7;
vector<int> G[MAXN];
long long f[MAXN];
int in[MAXN];
queue<int> que;
int n,m;

void topu(int u) {
    que.push(u);
    while(!que.empty()) {
        int q=que.front();
        que.pop();
        for(int i=0; i<G[q].size(); i++) {
            int p=G[q][i];
            in[p]--;
            f[p]+=f[q];
            f[p]%=MOD;
            if(in[p])continue;
            que.push(p);
        }
    }
}

int main() {
    freopen("three_squirrels.in","r",stdin);
    freopen("three_squirrels.out","w",stdout);
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        int num;
        scanf("%d",&num);
        for(int j=1; j<=num; j++) {
            int a;
            scanf("%d",&a);
            G[a].push_back(i);
            in[i]++;
        }
    }
    f[0]=1;
    topu(0);
    printf("%lld",f[n]%MOD);
    return 0;
}

 

posted @ 2017-07-02 21:26  zzzzx  阅读(527)  评论(0编辑  收藏  举报