首页 > 其他分享 >NC16544 简单环

NC16544 简单环

时间:2022-09-03 23:12:44浏览次数:71  
标签:int NC16544 简单 起点 回路 顶点 dp

题目链接

题目

题目描述

给定一张n个点m条边的无向图,求出图中所有简单环的数量。(简单环:简单环又称简单回路,图的顶点序列中,除了第一个顶点和最后一个顶点相同外,其余顶点不重复出现的回路叫简单回路。或者说,若通路或回路不重复地包含相同的边,则它是简单的)

输入描述

第一行三个数n m k (k在输出描述中提到)
接下来m行每行两个数u,v表示u到v之间存在一条边(无重边)

输出描述

输出k行每行1个整数
第i个数表示长度%k==i-1的简单环的数量(对998244353取模)
(只记录长度大于2的简单环的数量)

示例1

输入

4 6 3
1 2
2 3
3 4
4 1
2 4
1 3

输出

4
3
0

备注

n<=20
m<=n*(n-1)/2
k<=n

题解

知识点:状压dp。

比普通的TSP多了个环计数,应当在遍历每个状态时,查看起点和终点是否能够连接,能的话就给这个长度计数。为了避免重复计算,每次第一个 \(1\) 作为起点,选择终点应当在起点之后,防止出现不同的终点和起点对应同一个环的重复。最后应该除以二,消除顺时针逆时针的重复。

时间复杂度 \(O(m+n^22^n+q)\)

空间复杂度 \(O(n2^n+nm+q)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int mod = 998244353;
int g[27][27];
int dp[(1 << 20) + 7][27];///状态i且最后一个点为j时,除去连成环会重复的可能的所有方案
int ans[27];

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, q;
    cin >> n >> m >> q;
    for (int i = 1;i <= m;i++) {
        int u, v;
        cin >> u >> v;
        g[u][v] = 1;
        g[v][u] = 1;
    }
    for (int i = 1;i <= n;i++) dp[1 << i - 1][i] = 1;
    for (int i = 1;i < (1 << n);i++) {

        int s = 0;///规定每个状态的第一个1为起点
        for (int j = 1;j <= n;j++) {
            if (i & (1 << j - 1)) {
                s = j;
                break;
            }
        }
        int len = __builtin_popcount(i);

        for (int j = s + 1;j <= n;j++) {///枚举状态i的最后一个点
            ///最后一个点要在起点后面,因为最终会连成环,防止环形性重复计数,如..j...s.. <-> ..s...j..的等价情况 

            if (!(i & (1 << j - 1))) continue;
            for (int k = s;k <= n;k++) {///枚举上一次的最后一个点,只会在起点及其后面
                if (!(i & (1 << k - 1))) continue;
                if (g[j][k]) dp[i][j] = (dp[i][j] + dp[i ^ (1 << j - 1)][k]) % mod;///如果有通路,则可以连上
            }///计算合法链的方案

            if (g[s][j] && len >= 3)///起点和终点能连上且长度大于等于3时,属于能连成合法的环
                ans[len % q] = (ans[len % q] + dp[i][j]) % mod;
        }
    }
    for (int i = 0;i < q;i++)
        cout << 1LL * ans[i] * 499122177 % mod << '\n';///顺时针逆时针的重复计数消除
    return 0;
}

标签:int,NC16544,简单,起点,回路,顶点,dp
From: https://www.cnblogs.com/BlankYang/p/16653924.html

相关文章

  • 【C++】C++ qt 与 python 简单进程通讯
    前言准备用C++写一个简单的文字转语音的小东西,对C++qt这个怎么弄不太清楚(现在看到qt5.8后有个叫QTextToSpeech的东西),发现python调用一些库来进行文字转语音的发声比较简......
  • 简单加载器——分步指南
    简单加载器——分步指南HTML对于HTML,我们将只有一个带有“loader”类的div元素。<divclass="loader"></div>CSS我们只需根据需要设置宽度和高度,边框半径为50%......
  • springboot简单使用(4)
    1.9第九章Thymeleaf模版1.9.1认识ThymeleafThymeleaf是一个流行的模板引擎,该模板引擎采用Java语言开发模板引擎是一个技术名词,是跨领域跨平台的概念,在Java语......
  • 力扣20(java)-有效的括号(简单)
    题目:给定一个只包括'(',')','{','}','[',']' 的字符串s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括......
  • Sublime Text简单使用方法
    一.新建和保存文件一.点击文件,选择新建文件或者快捷键Ctrl+N二.另存文件,选择保存位置,这里项目的命名以.py为后缀二.保存代码快捷键Ctrl+S,上方文字出现小圆点表示未保......
  • 6-3 简单求和——10分
    本题要求实现一个函数,求给定的N个整数的和。函数接口定义:intSum(intList[],intN);其中给定整数存放在数组List[]中,正整数N是数组元素个数。该函数须返回N个List......
  • Redisson 分布式锁-简单使用
    Redission分布式锁一、引jar包<!--redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-st......
  • 简单理解 JavaScript 的词法作用域
    前言关于作用域的有关知识点有全局作用域、局部作用域、函数作用域、块级作用域、词法作用域、作用域链。作用域作用域就像是一个教室,上课时教室里面的人互相可见,A教室......
  • Vue.http同步执行,超简单
    Vue.http同步执行,超简单Vue.http同步执行,超简单解决方法:网上查找Vue.http设置同步,但感觉好复杂,我这个方法很简单,不用修改太多代码,只需在合适的位置添加async和await就行。......
  • 6-1 简单输出整数——10分
    本题要求实现一个函数,对给定的正整数N,打印从1到N的全部正整数。函数接口定义:voidPrintN(intN);其中N是用户传入的参数。该函数必须将从1到N的全部正整数顺序打印......