SRMS 531 DIV1

第二题:

Problem Statement

 

Pinguos are funny little monsters. Actually, there exist N different types of Pinguos (for simplicity numbered from 1 to N). Each midnight, each Pinguo dies. When a Pinguo dies, it gives birth to one or more new Pinguos. The types and numbers of these new Pinguos are uniquely determined by the type of the old, now dead, Pinguo. Please note that the total count of Pinguos never decreases, as each old Pinguo is replaced by at least one new Pinguo.


You are given a vector <string> transforms (containing N elements) describing for each type of Pinguo what types of Pinguos will arise from its dead body. For each i between 1 and N, element i-1 of transforms is a string containing a space-separated list of integers. These integers are the types of Pinguos that will arise from a dead Pinguo of type i. For example, if transforms[6] is "2 3 3", it means that when a Pinguo of type 7 dies, one Pinguo of type 2 and two Pinguos of type 3 will arise.


It is not hard to see that sometimes the number of Pinguos will grow towards infinity, eventually exceeding all bounds. However, there are some cases in which the number of Pinguos reaches a finite constant and then stays the same forever. (Note that these are the only two possible cases, as the total number of Pinguos never decreases. Also note that in the second case only the total number of Pinguos remains constant, their types may be changing every day.)


Initially you have a single Pinguo of type 1. You want to know what is the final (finite) number of Pinguos you will eventually end up with. Return this number modulo 1,000,000,007. If the count of Pinguos grows beyond all bounds, return -1 instead.

Definition

 
Class:MonsterFarm
Method:numMonsters
Parameters:vector <string>
Returns:int
Method signature:int numMonsters(vector <string> transforms)
(be sure your method is public)
 
 

Constraints

-transforms will contain between 1 and 50 elements, inclusive.
-Each element of transforms will contain between 1 and 50 characters, inclusive.
-Each element of transforms will be a list of integers separated by single spaces, with no extra leading or trailing spaces.
-Each integer in transforms will be between 1 and the number of elements in transforms, inclusive, with no leading zeros.

Examples

0) 
 
{"1"}
Returns: 1
After the Pinguo dies, you will always get another one of the same type. The total number of Pinguos is 1 forever.
1) 
 
{"1 1"}
Returns: -1
As the number of Pinguos doubles every day, the growth of their population will never terminate.
2) 
 
{"2", "3", "1"}
Returns: 1
The type of the Pinguo changes every day, but the total number of Pinguos stays the same.
3) 
 
{"1", "3 4", "2", "2"}
Returns: 1
You start with a Pinguo of type 1, and this is what you will have forever. However, note that if you had started with a Pinguo of type 2, your number of Pinguos would eventually grow beyond all bounds.
4) 
 
{"2 2", "3", "4 4 4", "5", "6", "7 7 7 7", "7"}
Returns: 24
5) 
 
{"2 3","5 7","2 4","5","6","4","7"}
Returns: 5

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.     


描述:这题题意就是有一种生物,这种生物有n类,每个类型的生物在死的时候会繁衍出至少1只的固定类型的生物,也就是生物的数量一定会增加,可能存在无穷增加,也可能最后趋于平衡,要求判断是否无限增加,如果不是的话,问最后剩下几只生物

分析:这题很明显的图论问题,仔细想一下就会发现,会不会无限增加关键在于是否出现环,也就是无向图的强连通分量,可是有环还不一定无限增长,这时需要满足两个条件:

1、强连通里的点至少有1个入度来自相同的连通块

2、并且这个点至少有两个出度

只要有一个点满足,就出现无限循环,注意点到自身也算是强连通

剩下的就是统计答案了,直接搜索模拟就行了,这一步一开始搞错了,纠结了好久,加上好久没做题,这题构思花了十几分钟,却用了接近5个小时来实现= =

代码:

#line 5 "MonsterFarm.cpp"
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;

#define PB push_back
#define MP make_pair

#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)

typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long LL;
typedef pair<int,int> PII;
const int mm=6666;
const int mn=111;

class MonsterFarm
{
public:
    int ver[mm],next[mm];
    int head[mn],dfn[mn],low[mn],id[mn],q[mn],out[mn];
    int index,num,edge,top;
    void addedge(int u,int v)
    {
        ++out[u];
        ver[edge]=v,next[edge]=head[u],head[u]=edge++;
    }
    void dfs(int u)
    {
        dfn[u]=low[u]=++index;
        q[top++]=u;
        int i,v;
        for(i=head[u]; i>=0; i=next[i])
            if(!dfn[v=ver[i]])dfs(v),low[u]=min(low[u],low[v]);
            else if(id[v]<0)low[u]=min(low[u],dfn[v]);
        if(dfn[u]==low[u])
        {
            id[u]=++num;
            while(q[--top]!=u)id[q[top]]=num;
        }
    }
    bool ok(int u)
    {
        int i,v;
        dfn[u]=1;
        for(i=head[u]; i>=0; i=next[i])
        {
            if(!dfn[v=ver[i]])
            {
                if(!ok(v))return 0;
            }
            if(id[u]==id[v])
            {
                if((++low[v]>0)&&out[v]>1)return 0;
            }
        }
        return 1;
    }
    bool tarjan(int n)
    {
        int i;
        for(i=index=num=top=0; i<=n; ++i)dfn[i]=0,id[i]=-1;
        dfs(1);
        for(i=0; i<=n; ++i)dfn[i]=low[i]=0;
        return ok(1);
    }
    int numMonsters(vector <string> transforms)
    {
        int i,j,k;
        for(edge=i=0; i<=transforms.size(); ++i)head[i]=-1,out[i]=0;
        for(i=0; i<transforms.size(); ++i)
        {
            for(j=k=0; j<transforms[i].size(); ++j)
                if(transforms[i][j]!=' ')
                {
                    k=k*10+transforms[i][j]-'0';
                }
                else
                {
                    addedge(i+1,k);
                    k=0;
                }
            if(k)addedge(i+1,k);
        }
        if(tarjan(transforms.size()))
        {
            int l,r,u,v,ans=0;
            for(r=i=0; i<=transforms.size(); ++i)out[i]=0;
            out[id[1]]=k=1;
            while(k)
            {
                k=0;
                for(r=i=0; i<=transforms.size(); ++i)dfn[i]=low[i]=0;
                dfn[1]=q[r++]=1;
                for(l=0; l<r; ++l)
                {
                    j=1;
                    for(i=head[u=q[l]]; i>=0; i=next[i])
                    {
                        if(!dfn[v=ver[i]])dfn[q[r++]=v]=1;
                        if(id[v]!=id[u])
                        {
                            j=0;
                            out[id[v]]+=out[id[u]];
                            if(out[id[v]]>=1000000007)out[id[v]]%=1000000007;
                        }
                    }
                    if(j&&out[id[u]])
                    {
                        k=1;
                        ans+=out[id[u]];
                        if(ans>=1000000007)ans%=1000000007;
                    }
                    out[id[u]]=0;
                }
            }
            return ans;
        }
        else return -1;
    }


};



// Powered by FileEdit
// Powered by TZTester 1.01 [25-Feb-2003]
// Powered by CodeProcessor


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值