zoukankan      html  css  js  c++  java
  • CF 11D

    题目:传送门

    思路:状压dp(i,j) 表示以最低位1的位号作起点(避免重复,环上任意点都能做起点,因此在这里规定一个起点,而且枚举状态时,会优先枚举低位再枚举高位),经过的点集为i,以j作为当前路径临时终点的方案数,  这里的路径可以理解为“不完整的环” “假设环”;

       转移方程 :若 j 和 k(k>=起点) 之间有边 ,则 dp(i,j) ——> dp(i|1<<k,k)  ,在路径末,加入k点 ;(如果k就是起点,那么就把dp值加入答案中,这里要注意类似1-2-1的环(实际上就是无向边)是不合法的)

       详细解释见代码:

       

     1 #include<bits/stdc++.h>
     2 /*
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<vector>
     7 #include<cctype>
     8 #include<queue>
     9 #include<algorithm>
    10 #include<map>
    11 #include<set>
    12 */
    13 #pragma GCC optimize(2)
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int,int> pii;
    17 typedef pair<double,double> pdd;
    18 const int N=20;
    19 const int M=3005;
    20 const int inf=0x3f3f3f3f;
    21 const LL mod=1e9+7;
    22 const double eps=1e-9;
    23 const long double pi=acos(-1.0L);
    24 #define ls (i<<1)
    25 #define rs (i<<1|1)
    26 #define fi first
    27 #define se second
    28 #define pb push_back
    29 #define mk make_pair
    30 #define mem(a,b) memset(a,b,sizeof(a))
    31 LL read()
    32 {
    33     LL x=0,t=1;
    34     char ch;
    35     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
    36     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    37     return x*t;
    38 }
    39 LL dp[1<<N][N];//dp(i,j) , 表示在i的状态下(路径经过的点),以 i的最低位的位号作起点,以j作为临时终点的 路径个数 "假设环"个数 (先假设这个路径能成为环,在dp加点验证)
    40 int n,m;
    41 int pic[N][N];
    42 int qs(int x)
    43 {
    44     int i;
    45     for(i=0;(1<<i&x)==0;i++);
    46     return i;
    47 }
    48 int main()
    49 {
    50     n=read(),m=read();
    51     for(int i=1;i<=m;i++)
    52     {
    53         int x=read(),y=read();
    54         pic[x-1][y-1]=1;
    55         pic[y-1][x-1]=1;
    56     }
    57     for(int i=0;i<n;i++) dp[1<<i][i]=1;//赋初值(创建以i为起点的路径"假设环")
    58     int lim=1<<n;
    59     LL ans=0;
    60     for(int i=1;i<lim;i++)
    61     {
    62         int s=qs(i);//s为当前状态下的路径起点(假设s是某个环的起点,再通过向路径中加点来验证,我们可以把这个路径称作"假设环")
    63         for(int e=s;e<n;e++) //枚举路径终点(假设环的临时终点)
    64         {
    65             if(dp[i][e]==0) continue;//这个语句的判定包括了 对于(1<<e&i)的判定,由转移方程可知 dp[x][k] 其中 (1<<k&x)==1 ,这样的dp值才可能被访问到
    66             //if(1<<e&i)
    67             for(int k=s;k<n;k++) //向路径中加入新点,且这个新点的编号不能比s小,因为s是"假设环"的起点不能被替代【避免出现类似于 1-2-3-1 和 2-3-1-2 重复的情况】
    68             {
    69                 if(!pic[e][k]) continue;
    70                 if(1<<k&i)
    71                 {
    72                     if(k==s) ans+=dp[i][e];
    73                 }
    74                 else dp[i|1<<k][k]+=dp[i][e];//向"假设环"中加点
    75             }
    76         }
    77     }
    78     printf("%lld
    ",(ans-m)/2);
    79     //可以在dp的过程中除掉只有两个点的环(只有第s、e位上为1的环,相当于边数),也可以直接在答案中减m //if(k==s&&(1<<s|1<<e)!=i)
    80     //除以2是因为 ,长度>=3的环会被算两次,例如1-2-3-4-1 和 1-4-3-2-1 ;而 1-2-1 只是会被算一次(自行模拟)
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    SQL Server 2005 Integration Services (SSIS)数据源之MySQL
    SQL Server 2005 Integration Services (SSIS)数据源之Sybase
    oracle10g 监听服务无法启动
    创建一个People类型,有年龄、工资、性别三个属性。 定义一个方法叫做找对象,找对象方法传过来一个人;
    基于组件的C#农历算法
    ASP.NET中实现中文简/繁体自动转换的类
    最牛的QQ资料
    单一登陆(Single Signon)问题
    Smart Client Case Study Source Code Download from MSDN China
    简历制作 | 论文资源 | 考试认证 | 招聘求职 | 文学艺术 | 外语学习
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12865312.html
Copyright © 2011-2022 走看看