状压dp-A Simple Task

A Simple Task time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices or edges.

Input

The first line of input contains two integers n and m (1 ≤ n ≤ 19, 0 ≤ m) – respectively the number of vertices and edges of the graph. Each of the subsequent m lines contains two integers a and b, (1 ≤ a, b ≤ na ≠ b) indicating that vertices a and b are connected by an undirected edge. There is no more than one edge connecting any pair of vertices.

Output

Output the number of cycles in the given graph.

Examples input Copy
4 6
1 2
1 3
1 4
2 3
2 4
3 4
output Copy
7
Note

The example graph is a clique and contains four cycles of length 3 and three cycles of length 4.

 看到19这个很小的数字,很容易让人联想到状压。只是比赛的时候写不出转移方程,自闭5h。出来之后才把题目补上。

代码参考https://www.luogu.org/blog/812-xiao-wen/solution-cf11d,感谢大佬的讲解。

 

 

#include<bits/stdc++.h>

#define ll long long
using namespace std;

int n,m,t,u,v;
bool a[20][20];//邻接矩阵
ll ans,f[600001][20];//dp数组,第一维记录点的状态,第二维记录起点


int main(){
    
    cin>>n>>m;
    t=1<<n;
    for(int i=1;i<=m;++i){
        cin>>u>>v;
        u--;
        v--;
        a[u][v]=a[v][u]=1;
    }
    for(int i=0;i<n;++i)
        f[1<<i][i]=1;//初始化
for(int i=1;i<=t;++i){ for(int j=0;j<n;++j){ if(!f[i][j])continue; for(int k=0;k<n;++k){ if(!a[j][k])continue;//如果不存在边,跳过 if((i&-i)>(1<<k))continue;//如果起点不是k,跳过//这里i&-i取得的是起点 if(1<<k&i){//如果这个点在里面 if(1<<k==(i&-i))//如果k就是起点,加入答案 ans+=f[i][j]; } else f[i|1<<k][k]+=f[i][j];//不在里面就加进入 } } } cout<<(ans-m)/2<<endl;//注意去重和两点成环的非法情况 return 0; }

 

上一篇:[cf1025D][区间dp]


下一篇:A trip through the Graphics Pipeline 2011_03