题目背景

$Billions\ of\ lighthouses...stuck\ at\ the\ far\ end\ of\ the\ sky.$


题目描述

平面有$n$个灯塔,初始时两两之间可以相互交流;但由于地形原因,有$m$对灯塔之间无法进行直接的交流。也就是一张完全图缺少了$m$条边。
    $River$想把这$n$个灯塔连成一个环,使得$n$个等他都在环上,并且环上相邻的两个灯塔能进行直接交流。$River$想知道这样做的方案数是多少,两种方案被认为是不同的,当且仅当有两个灯塔$u,v$,他们在一种方案中在环上相邻,而在另一种方案中相反。
    答案可能很大,你只需要输出对${10}^9+7$取模的结果。


输入格式

第一行两个整数$n,m$。
接下来$m$行,每行描述一条缺少的边。


输出格式

一行一个整数表示答案。


样例

样例输入1:

4 1
1 2

样例输出1:

1

样例输入2:

10 3
1 9
3 8
2 7

样例输出2:

87840


数据范围与提示

样例$1$解释:

唯一的方案是(1,3,2,4)依次连成环。

数据范围:

对于所有数据,有$3\leqslant n\leqslant {10}^7,0\leqslant m\leqslant \min(20,\frac{n(n-1)}{2})$。输入的边中没有重边。


题解

题目实际上球的就是哈密顿回路的数量。由于$m$很小,考虑容斥。
    枚举删除的边的某个子集$S$,设$f_S$表示有多少条哈密顿回路至少包含$S$集合中的边,答案就是$\sum_S(-1)^{|S|}\times f_S$。
    怎么算$f_S$呢?首先判掉$f_S=0$的情况,这包含以下两种情况:
        $\alpha.$仅考虑$S$中的边时,某个点的度数大于$2$。
        $\beta.$出现了环,并且这个环的大小不为$n$。
    特判掉$S$本身就是一个哈密顿回路的情况;假设$S$中的边构成了$k$条链,那么$f_S=s{k-1}\times (n-|S|-1)!$。
    证明:考虑将一条链看成一个点,那么总共有$n-|S|$个点,其环排列方案数为$(n-|S|-1)!$;每条链都可以翻转,因此乘上$2^k$;又由于一条哈密顿回路对应了两个环排列(正反两个方向),还要除以$2$。

时间复杂度:$\Theta(2^m\times m)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long jc[10000001];
int fa[10000001];
pair<int,int> pos[10000001];
int tot;
long long ans;
int cnt[10000001],vis[10000001],g[10000001];
int que[10000001];
map<pair<int,int>,bool> h;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
long long qpow(long long x,long long y)
{long long res=1;while(y){if(y&1)res=res*x%1000000007;x=x*x%1000000007;y>>=1;}return res;}
long long solve(int x)
{
int sum=0,k=que[0]=0;
bool flag=0;
for(int i=1;i<=tot;i++)
if((x>>(i-1))&1)
{
que[++que[0]]=i;
fa[pos[i].first]=pos[i].first;
fa[pos[i].second]=pos[i].second;
vis[pos[i].first]=vis[pos[i].second]=g[pos[i].first]=g[pos[i].second]=0;
}
for(int i=1;i<=que[0];i++)
{
if(!vis[pos[que[i]].first])sum++;
if(!vis[pos[que[i]].second])sum++;
if(vis[pos[que[i]].first]==2||vis[pos[que[i]].second]==2)return 0LL;
vis[pos[que[i]].first]++;
vis[pos[que[i]].second]++;
}
for(int i=1,u,v;i<=que[0];i++)
{
if((u=find(pos[que[i]].first))==(v=find(pos[que[i]].second)))flag=1;
fa[u]=v;
}
for(int i=1,u;i<=que[0];i++)
if(!g[u=find(pos[que[i]].first)]){g[u]=1;k++;}
if(flag&&(cnt[x]!=n||k>1))return 0LL;
long long res=jc[n-sum+k-1]*qpow(2,k)%1000000007*qpow(2,1000000005)%1000000007;
return (cnt[x]&1)?-res:res;
}
int main()
{
jc[0]=1;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x==y||h[make_pair(x,y)])continue;
h[make_pair(x,y)]=1;
pos[++tot]=make_pair(x,y);
}
for(int i=1;i<=n;i++)jc[i]=1LL*i*jc[i-1]%1000000007;
for(int i=0;i<(1<<tot);i++)cnt[i]=cnt[i>>1]+(i&1);
for(int i=0;i<(1<<tot);i++)ans=(ans+solve(i))%1000000007;
printf("%lld",(ans+1000000007)%1000000007);
return 0;
}

rp++

[CSP-S模拟测试]:Lighthouse(哈密顿回路+容斥)的更多相关文章

  1. [CSP-S模拟测试]:阴阳(容斥+计数+递推)

    题目传送门(内部题16) 输入格式 第一行两个整数$n$和$m$,代表网格的大小.接下来$n$行每行一个长度为$m$的字符串,每个字符若为$W$代表这个格子必须为阳,若为$B$代表必须为阴,若为$?$ ...

  2. [CSP-S模拟测试]:多维网格(组合数学+容斥)

    题目传送门(内部题138) 输入格式 输入数据第一行为两个整数$d,n$. 第二行$d$个非负整数$a_1,a_2,...,a_d$.     接下来$n$行,每行$d$个整数,表示一个坏点的坐标.数 ...

  3. [CSP-S模拟测试]:连连看(图论+容斥)

    题目传送门(内部题74) 输入格式 输入文件$link.in$ 第一行三个整数$n,m,k$,之间用空格隔开,$n,m$表示地图行数和列数,$k$表示每个方块周围相邻的位置(至多有$4$个,至少有$2 ...

  4. [CSP-S模拟测试]:建设城市(city)(组合数学+容斥)

    题目传送门(内部题8) 输入格式 一行三个整数$n,m,k$. 输出格式 一行一个整数表示答案.对$998244353$取模. 样例 样例输入 3 7 3 样例输出 数据范围与提示 对于10%的数据, ...

  5. csp-s模拟测试59(10.4)「Reverse」(set)·「Silhouette」(容斥)

    A. Reverse 菜鸡wwb又不会了..... 可以线段树优化建边,然而不会所以只能set水了 发现对于k和当前反转点固定的节点x确定奇偶性所到达的节点奇偶性是一定的 那么set维护奇偶点,然后每 ...

  6. 【GDOI2016模拟3.16】幂(容斥 + 模型复杂转化)

    [GDOI2016模拟3.16]幂 \(X\in[1,A],Y\in[1,B]\),问:\(x^y\)的不用取值个数. \(A,B\)都是\(10^9\)级别. 然后我们开搞. 首先,假设一个合法的\ ...

  7. hdu 6169 Senior PanⅡ Miller_Rabin素数测试+容斥

    Senior PanⅡ Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Pr ...

  8. 2018.10.30 NOIP模拟 字胡串(单调栈+容斥)

    传送门 对于每个点,用单调栈求出它左右第一个比他大的位置. 然后对每个点O(logai)O(log_{a_i})O(logai​​)求出第一个拥有跟它不同二进制位的位置. 然后容斥一下就行了. 代码

  9. NOIp模拟赛 巨神兵(状压DP 容斥)

    \(Description\) 给定\(n\)个点\(m\)条边的有向图,求有多少个边集的子集,构成的图没有环. \(n\leq17\). \(Solution\) 问题也等价于,用不同的边集构造DA ...

随机推荐

  1. elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题

    开发完后台管理系统的弹出框模块,被添加拖拽和拉伸功能,看了很多网上成熟的帖子引到项目里总有一点问题,下面是根据自己的需求实现的步骤: 首先在vue项目中创建一个js文件eg:dialog.js imp ...

  2. jQuery将字符串转换为数字

    1:parseInt(string)  parseInt("1234blue"); //returns 1234 parseInt("123"); //retu ...

  3. mysql 主从复制(mysql双机热备的实现)

    转:http://blog.csdn.net/qq394829044/article/details/53203645 Mysql数据库没有增量备份的机制,当数据量太大的时候备份是一个很大的问题.还好 ...

  4. DMA的认识

    DMA的简单了解与认识 DMA就是为了减轻CPU的负担来设置的存储方式.当从外设取到的数据就不需要经过内核操作,而是通过DMA直接把外设的数据放到内存SRAM中,这样就会减少CPU的负担,让CPU在此 ...

  5. spring bean-- autowired的正确用法

    这两天用idea写spring注入的时候每一次 @Autowired Worker worker; 都会报黄,用过这个ide的都知道,说明你代码需要重构了. 然后提示的信息是 Spring Team ...

  6. 并行开发 1.Parallel

    原文:8天玩转并行开发——第一天 Parallel的使用 随着多核时代的到来,并行开发越来越展示出它的强大威力,像我们这样的码农再也不用过多的关注底层线程的实现和手工控制, 要了解并行开发,需要先了解 ...

  7. Codeforces Round #554 (Div. 2) C.Neko does Maths (gcd的运用)

    题目链接:https://codeforces.com/contest/1152/problem/C 题目大意:给定两个正整数a,b,其中(1<=a,b<=1e9),求一个正整数k(0&l ...

  8. Sass函数-数字函数-floor()函数

    floor() 函数刚好与 ceil() 函数功能相反,其主要将一个数去除其小数部分,并且不做任何的进位.也就是只做舍,不做入的计算: >> floor(2.1) 2 >> f ...

  9. 无法用另一台电脑上的navicat链接主机数据库lost connection toMYSQl server at "handshake":reading inital communication packet,system error:34

    同事要用navicat登陆我的数据库,主机地址和密码都没错,但是报错,lost connection toMYSQl server at "handshake":reading i ...

  10. 【串线篇】SQL映射文件-resultMap自定义封装

    mybatis默认封装规则: 1).按照列明和属性名一一对应的规则(不区分大小写) 2).如果不一一对应: 1).开启驼峰命名(数据库aaa_bbb, 程序中aaaBbb) 2).起别名 3).自定义 ...