SRM 628 DIV2

250  想想就发现规律了。

500  暴力,括号匹配。

1000

给一个f数组,如果i存在,那么f[i]也得存在,问这样的集合有多少种。

先拓扑一下,dp[i] = mul(dp[son]+1)最后环里面的元素的乘积是结果。

#include <iostream>

#include <cstdio>

#include <string>

#include <algorithm>

#include <stdlib.h>

#include <vector>

#include <cmath>

#include <queue>

#include <set>

#include <stack>

using namespace std;

#define LL long long

int p[51][51],o[51],flag[51],nt[51];

LL dp[51];

LL temp;

void dfs(int x)

{

    flag[x] = 1;

    temp *= dp[x];

    if(flag[nt[x]] == 1)

    return ;

    flag[nt[x]] = 1;

    dfs(nt[x]);

}

class InvariantSets

{

    public :

    LL countSets(vector <int> f)

    {

        int i,j,n,z;

        LL ans = 1;

        n = f.size();

        for(i = 0;i < n;i ++)

        {

            p[i][f[i]] = 1;

            dp[i] = 1;

            nt[i] = f[i];

            o[f[i]] ++;

        }

        for(;;)

        {

            z = 0;

            for(i = 0;i < n;i ++)

            {

                if(o[i] == 0&&!flag[i])

                {

                    flag[i] = 1;

                    z = 1;

                    for(j = 0;j < n;j ++)

                    {

                        if(p[i][j] == 1&&!flag[j])

                        {

                            dp[j] *= (dp[i] + 1);

                            o[j] --;

                        }

                    }

                }

            }

            if(!z) break;

        }

        for(i = 0;i < n;i ++)

        {

            temp = 1;

            if(flag[i] == 0)

            {

                dfs(i);

                ans *= (temp+1);

            }

        }

        return ans;

    }

};
View Code

 

你可能感兴趣的:(div)