【ARC062F】 Painting Graphs with AtCoDeer 点双连通分量+polya定理
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定理的更多相关文章
- AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】
题目分析: 如果一个双连通分量是简单环,那么用polya原理计数循环移位即可. 如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换. 如果一条边是桥,那么直接乘以k ...
- [ARC062F]Painting Graphs with AtCoDeer
题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...
- [Arc062] Painting Graphs with AtCoDeer
[Arc062] Painting Graphs with AtCoDeer Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色.你可以对一张染色了的图进行若干次操作, ...
- ARC 062 F - Painting Graphs with AtCoDeer 割点 割边 不动点 burnside引理
LINK:Painting Graphs with AtCoDeer 看英文题面果然有点吃不消 一些细节会被忽略掉. 问每条边都要被染色 且一个环上边的颜色可以旋转. 用c种颜色有多少本质不同的方法. ...
- 【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer
题解 考虑一个点双(因为是简单环),如果没有环(两点一线),那么乘上K 如果有一个环,那么用polya定理,每个置换圈有gcd(i,n)个循环节 如果有两个及以上的环,任何一种置换都合法,那么只和每个 ...
- [atARC062F]Painting Graphs with AtCoDeer
求出点双后缩点,对于点双之间,显然不存在简单环,即每一个简单环一定在一个点双内部,换言之即每一个点双可以独立的考虑,然后将结果相乘 (对于点双之间的边任意染色,即若有$s$条边,还会有$k^{s}$的 ...
- ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)
似乎好久都没写博客了....赶快来补一篇 题意 给你一个 \(n\) 个点 , 没有重边和自环的图 . 有 \(m\) 条边 , 每条边可以染 \(1 \to k\) 中的一种颜色 . 对于任意一个简 ...
- ARC062F AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer Burnside 引理
题目传送门 https://atcoder.jp/contests/arc062/tasks/arc062_d 题解 首先对整张图做 Tarjan 点双. 对于一个点双,如果是由一条边构成的,那么很显 ...
- 2018.09.20 atcoder Painting Graphs with AtCoDeer(tarjan+polya)
传送门 一道思维题. 如果没有环那么对答案有k的贡献. 如果恰为一个环,可以用polya求贡献. 如果是一个有多个环重叠的双联通的话,直接转化为组合数问题(可以证明只要每种颜色被选取的次数相同一定可以 ...
随机推荐
- hadoop集群配置和在windows系统上运用java操作hdfs
安装 配置 概念 hadoop常用shell命令 使用java操作hadoop 本文介绍hadoop集群配置和在windows系统上运用java操作hdfs 安装 http://mirror.bit. ...
- java成神之——Fork/Join基本使用
Fork/Join 大任务分小任务,小任务结果合并 ForkJoinPool pool = new ForkJoinPool(); RecursiveTask<Integer> task1 ...
- 第二章 Java内存区域与内存溢出异常(待续)
·········
- leetcode709
string toLowerCase(string str) { transform(str.begin(), str.end(), str.begin(), ::tolower); return s ...
- 一些c++
1.static 静态局部对象: 一旦被创建,在程序结束前都不会被撤销.当定义静态局部对象的函数结束时,静态局部对象不会撤销. 2.内联函数: 避免函数调用的开销. 在函数返回类型前加上关键字 inl ...
- 关于CountDownLatch控制线程的执行顺序
在上一篇文章中说过使用thread.join()方法.newSingleThreadExecutor单线程池来控制线程执行顺序.在文章的末尾我提出了一种构想,可否使用经典的生产者和消费者模型来控制执行 ...
- 开坑数位dp
[背景] 在10月3日的dp专练中,压轴的第6题是一道数位dp,于是各种懵逼. 为了填上这个留存已久的坑,蒟蒻chty只能开坑数位dp了. [例题一][HDU2089]不要62 题目大意:给你一个区间 ...
- Redis安装文档
1.前置条件 前置条件:linux已经可以上网,参考:https://www.cnblogs.com/ZenoLiang/p/10201875.html 2.安装redis 2.1依赖包检查 1. ...
- <c:out>标签中有一个escapeXml属性 如果为escapeXml="false",则将其中的html、xml解析出来。
<td><c:out value="${s.name}" escapeXml="false"></c:out></td ...
- c# 判断网络地址是否存在
方法一:网络地址存在,有可能可以访问,也有可能不能访问.此方法用来判断地址存在. static bool UrlIsExist(String url) { System.Uri u = null; t ...