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

 

posted @ 2014-07-29 18:20  Naix_x  阅读(411)  评论(0编辑  收藏  举报