• E


    题:https://codeforces.com/contest/1395/problem/E

    题意:给定n个点m条边的图,给定k,每个点的出度不会超过k,定义k个元素的ci数组:对于每个节点度数di,那么节点 i 要走第cdi小边权的边。对于图上的每个点作为起点进行若干步ci数组操作都能回到起点,问这样的ci数组有多少个。

    分析:由于1<=k<=9&&1<=ci<=i,那么最多有9!种ci数组,即我们可以通过枚举来判断其是否满足条件。

       其实我们只要考虑每个点的下一个点会到哪个点即可,那么要求每个点出发都能回到原点的条件就转化为每个点的下一个点组成的点集为1~n(1到n恰好都只出现一次)。

       那么我们考虑用哈希值来表示点集,对于每个度数值有若干个点,累加每个第 i 小值节点对应的哈希值;

       因为哈希值的计算满足结合律,所以直接把枚举的ci数组的哈希值与1~n和哈希值比较即可完成判断。

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define ull unsigned long long
    #define pii pair<int,int>
    #define MP make_pair
    const int M=2e5+5;
    const int H=1e9+7;
    vector<pii >g[M];
    
    ull goal,a[20][20],Hash[M];
    int n,m,k,ans;
    void dfs(int u,ull now){
        if(u==k+1){
            ans+=(now==goal);
            return ;
        }
        for(int i=1;i<=u;i++)
            dfs(u+1,now+a[u][i]);
    
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for(int u,v,w,i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            g[u].pb(MP(w,v));
        }
        Hash[0]=1,goal=0;
        for(int i=1;i<=n;i++){
            Hash[i]=Hash[i-1]*H;
            goal+=Hash[i];
        }
    
        for(int i=1;i<=n;i++){
            sort(g[i].begin(),g[i].end());
            int tot=g[i].size();
            for(int j=0;j<tot;j++)
                a[tot][j+1]+=Hash[g[i][j].second];
        }
        ans=0;
        dfs(1,0);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    MySQL-5.7.26解压版安装教程
    asp.net core 系列之Configuration
    java之初识hibernate
    java框架学习系列
    java之struts2之异常处理
    java之struts2之ajax
    java之servlet之文件下载
    列出连通集
    幸运数
    英文单词排序
  • 原文地址:https://www.cnblogs.com/starve/p/13495004.html
Copyright © 2020-2023  润新知