Description

给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色。

你可以对一张染色了的图进行若干次操作,每次操作形如,在图中选择一个简单环(即不经过相同点的环),并且将其颜色逆时针旋转一个单位。

形式的说,假设你选择的环上的边按顺序依次是e1, e2, ... ,ek,那么经过一次操作后ei mod n+1的颜色会变成操作前ei的颜色。

两种染色方案被认为是本质相同的,当且仅当其中一种染色后的图经过若干次操作后可以变成另一种染色后的图。

问有多少本质不同的染色方案,输出对10^9+7取模。

Input

第一行三个正整数N M K

接下来M行每行两个正整数表示图中的一条边。

Output

输出一行一个非负整数表示答案。

Sample Input

Sample Input 1
4 4 2
1 2
2 3
3 1
3 4 Sample Input 2
5 2 3
1 2
4 5 Sample Input 3
11 12 48
3 1
8 2
4 9
5 4
1 6
2 9
8 3
10 8
4 10
8 6
11 7
1 8

Sample Output

Sample Output 1
8 Sample Output 2
9 Sample Output 3
569519295

HINT

1≤N≤50

1≤M, K≤100

Sol

每个点双联通分量的贡献是独立的,我们用tarjan找出每个点双联通分量,然后分类讨论:

如果只是一条不属于双联通分量的边,那么贡献是k;

如果是个简单环,那么就转化成项链计数问题,这个要用polya定理来解决,具体地:

\(res=\sum_{i=1}^{n}gcd(i,n)\)

如果是好多环拼一起的,可以发现分量中任何边都能通过旋转交换,那么我们枚举每个颜色有\(x_i\)个,这就转化成不定方程解个数,用隔板法解决,即\(C_{n+k-1}^{k-1}\)。

显然第一种和第二种在tarjan中会当成一种处理,而且他们也是等价的。第三种在遇到\(low[to[i]]>=dfn[x]\)的时候判一下,如果有个点被边的出点经过了多次,说明是情况三,然后找出边总数然后计算即可。

细节:1.反向边记得也要打vis标记 2.当前边也要退栈以及进行计算贡献 3.邻接表下标不要从0开始,如果从0开始的话请把栈数组赋值为-1。

Code

#include <bits/stdc++.h>
#define ll long long
#define P 1000000007ll
using namespace std;
int x,y,n,m,k,I,hed[51],nex[201],to[201],low[201],dfn[201],vis[51],top,s[201],cnt=1,use[201];
ll ans=1,fac[201],mi[201],ifa[201],inv[201];
void add(int x,int y){to[++cnt]=y;nex[cnt]=hed[x];hed[x]=cnt;}
void dfs(int x)
{
dfn[x]=low[x]=++I;
for(int i=hed[x];i!=-1;i=nex[i]) if(!use[i]&&!use[i^1])
{
s[++top]=i;use[i]=use[i^1]=1;
if(!dfn[to[i]])
{
dfs(to[i]);low[x]=min(low[x],low[to[i]]);
if(low[to[i]]>=dfn[x])
{
bool cir=1;int tot=0;ll res=0;
for(int j=top;s[j+1]!=i;j--,tot++) if(vis[to[s[j]]]) cir=0;else vis[to[s[j]]]=1;
if(cir){for(int j=0;j<tot;j++) res=(res+mi[__gcd(tot,j)])%P;res=res*inv[tot]%P;}
else res=fac[tot+k-1]*ifa[k-1]%P*ifa[tot]%P;
ans=ans*res%P;
for(;s[top+1]!=i;top--) vis[to[s[top]]]=0;
}
}
else low[x]=min(low[x],dfn[to[i]]);
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);mi[0]=fac[0]=fac[1]=ifa[0]=ifa[1]=inv[1]=1;mi[1]=k;memset(hed,-1,sizeof(hed));
for(int i=2;i<=m+k;i++) mi[i]=mi[i-1]*k%P,fac[i]=i*fac[i-1]%P,inv[i]=(P-P/i)*inv[P%i]%P,ifa[i]=ifa[i-1]*inv[i]%P;
for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
printf("%lld\n",ans);
}

【ARC062F】 Painting Graphs with AtCoDeer 点双连通分量+polya定理的更多相关文章

  1. AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】

    题目分析: 如果一个双连通分量是简单环,那么用polya原理计数循环移位即可. 如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换. 如果一条边是桥,那么直接乘以k ...

  2. [ARC062F]Painting Graphs with AtCoDeer

    题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...

  3. [Arc062] Painting Graphs with AtCoDeer

    [Arc062] Painting Graphs with AtCoDeer Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色.你可以对一张染色了的图进行若干次操作, ...

  4. ARC 062 F - Painting Graphs with AtCoDeer 割点 割边 不动点 burnside引理

    LINK:Painting Graphs with AtCoDeer 看英文题面果然有点吃不消 一些细节会被忽略掉. 问每条边都要被染色 且一个环上边的颜色可以旋转. 用c种颜色有多少本质不同的方法. ...

  5. 【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer

    题解 考虑一个点双(因为是简单环),如果没有环(两点一线),那么乘上K 如果有一个环,那么用polya定理,每个置换圈有gcd(i,n)个循环节 如果有两个及以上的环,任何一种置换都合法,那么只和每个 ...

  6. [atARC062F]Painting Graphs with AtCoDeer

    求出点双后缩点,对于点双之间,显然不存在简单环,即每一个简单环一定在一个点双内部,换言之即每一个点双可以独立的考虑,然后将结果相乘 (对于点双之间的边任意染色,即若有$s$条边,还会有$k^{s}$的 ...

  7. ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)

    似乎好久都没写博客了....赶快来补一篇 题意 给你一个 \(n\) 个点 , 没有重边和自环的图 . 有 \(m\) 条边 , 每条边可以染 \(1 \to k\) 中的一种颜色 . 对于任意一个简 ...

  8. ARC062F AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer Burnside 引理

    题目传送门 https://atcoder.jp/contests/arc062/tasks/arc062_d 题解 首先对整张图做 Tarjan 点双. 对于一个点双,如果是由一条边构成的,那么很显 ...

  9. 2018.09.20 atcoder Painting Graphs with AtCoDeer(tarjan+polya)

    传送门 一道思维题. 如果没有环那么对答案有k的贡献. 如果恰为一个环,可以用polya求贡献. 如果是一个有多个环重叠的双联通的话,直接转化为组合数问题(可以证明只要每种颜色被选取的次数相同一定可以 ...

随机推荐

  1. Linux - 归档和压缩

    归档 归档就是将多个文件或目录合并成一个文件 归档的目的就是方便备份.还原及文件的传输操作 tar 命令:将多个文件或目录归档到一个文件中,可以根据需要只还原归档文件中的某些指定的文件 c:创建,v: ...

  2. Wireshark捕获非加密的数据包

    启动监听模式 root@sch01ar:~# airmon-ng start wlan0 启动Wireshark工具 root@sch01ar:~# wireshark 选择接口,这里选择wlan0m ...

  3. python's twenty-fifth day for me 模块

    模块: py文件就是模块. python之所以好用,因为模块多. 内置模块:python安装的时候自带的. 扩展模块:别人写好的,需要安装后可直接使用. 自定义模块:自己写的模块. 序列化模块: 能存 ...

  4. 3.Periodic Tasks

     celery beat是一个调度器,它可以周期内指定某个worker来执行某个任务.如果我们想周期执行某个任务需要增加beat_schedule配置信息.   broker_url='redis:/ ...

  5. STM32用有源蜂鸣器实现闹钟的声响

    有源蜂鸣器的声音是固定的,工作电压恒定,改变通断电的时间获得不同时长的音响,譬如连续音.快速短音.慢速长音(类似莫尔斯电报)来区分不同的报警信息. 简单的说,有源蜂鸣器只能发出一种声音,因为它的频率是 ...

  6. RAD 10 蓝牙

    http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Bluetooth.TBluetoothLEManager.StartDiscov ...

  7. windows下利用VMware安装mac:构建…

    安装条件: 硬件:一台拥有支持虚拟技术的64位双核处理器和2GB以上内存的PC. 注意:运行MAC OS,需要电脑支持虚拟技术(VT),安装时,需要将VT启动,在BIOS中开启. 关于如何检测你的电脑 ...

  8. Linux ping不通外网

    在linux中ping www.baidu.com 无法ping通,可能原因是DNS没配置好 方法一: 修改vi /etc/resolv.conf  增加如下内容: nameserver 114.11 ...

  9. vware 中 red hat linux NAT模式上网配置

    NAT模式的具体配置NAT方式:虚拟机可以上外网,可以访问宿主计算机所在网络的其他计算机(反之不行). 未修改之前的eth0

  10. 解决nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)

    nginx先监听了ipv4的80端口之后又监听了ipv6的80端口,于是就重复占用了.更加坑人的是你去看了端口占用它又把80端口释放了,是不是很囧. 解决方案是编辑nginx的配置文件 修改这一段: