状压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; }

猜你喜欢

转载自www.cnblogs.com/wengsy150943/p/11228011.html