zoukankan      html  css  js  c++  java
  • [CF1394B] Boboniu Walks on Graph

    Description

    给定有向图,在图上走的时候,出度为 (i) 的边,只能走到边权大小为第 (c_i) 小的边上面,问 (c) 数组有多少种,要每个点都满足:从这个点开始走都可以回到这个点。每个点的入度都小于等于 (9)

    Solution

    最终每个点一定只会有一个出点,将 (p) 的出度为 (f[p]),则显然 (f[]) 一定是 (1..n) 的一个全排列

    考虑到 (f[]) 的关于 (c[]) 的各个位是独立的,因此可以分别枚举 (c) 的每一位,生成 (f[]) 的某些校验值(组合),与全排列比较即可,校验可以 hash,这里为了省事,对每一位预先生成一个随机数 (w[]),然后求和即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    const int mod = 1e12+7;
    
    int n,m,k,a[N],w[N],c[N],ans,stdsum;
    
    struct edge
    {
        int v,w;
        bool operator < (const edge &obj)
        {
            return w < obj.w;
        }
    };
    
    vector <edge> g[N];
    vector <int> res[N];
    vector <int> vec[N];
    
    void dfs(int p,int sum)
    {
        //cout<<"dfs "<<p<<" "<<sum<<endl;
        if(p==k+1)
        {
            //cout<<sum<<",";
            if(sum==stdsum) ++ans;
        }
        else
        {
            for(int i:res[p])
            {
                dfs(p+1,(sum+i)%mod);
            }
        }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>m>>k;
        for(int i=1;i<=m;i++)
        {
            int t1,t2,t3;
            cin>>t1>>t2>>t3;
            g[t1].push_back({t2,t3});
        }
    
    
        for(int i=1;i<=n;i++)
        {
            vec[g[i].size()].push_back(i);
        }
    
    
        for(int i=1;i<=n;i++)
        {
            sort(g[i].begin(),g[i].end());
        }
    
        for(int i=1;i<=n;i++)
        {
            w[i]=rand()*rand();
            stdsum+=w[i];
            stdsum%=mod;
        }
    
        for(int pos=1;pos<=k;pos++)
        {
            for(int val=0;val<pos;val++)
            {
                int tmp=0;
                for(int i:vec[pos])
                {
                    tmp+=w[g[i][val].v];
                }
                res[pos].push_back(tmp);
            }
        }
    
        for(int i=1;i<=k;i++)
        {
            if(res[i].size()==0) res[i].push_back(0);
        }
    
        dfs(1,0);
    
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    sql——查询出表中不为空或为空字段的总值数
    sql语句——根据身份证号提取省份、出生日期、年龄、性别。
    1.两数之和
    Java虚拟机
    【10.18】
    议论文:是否应该留学
    议论文:阅读能力
    应用文:线上广告
    通知(重点:格式)
    书信(重点:格式)
  • 原文地址:https://www.cnblogs.com/mollnn/p/13638032.html
Copyright © 2011-2022 走看看