zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Linux下MongoDB的基本操作
    PHP curl及并发curl封装函数实现
    根据ip地址获取地区信息的接口
    修改Samba服务的监听端口
    定时脚本更新svn文件
    第一次直面http的301跳转
    ASP.NET MVC 学习之路-6
    ASP.NET MVC 学习之路-5
    C#静态构造函数
    HTML5新特性学习-2
  • 原文地址:https://www.cnblogs.com/starve/p/13495004.html
Copyright © 2011-2022 走看看