求出点双后缩点,对于点双之间,显然不存在简单环,即每一个简单环一定在一个点双内部,换言之即每一个点双可以独立的考虑,然后将结果相乘

(对于点双之间的边任意染色,即若有$s$条边,还会有$k^{s}$的贡献)

对点双分类讨论(假设其有$n$个节点,$m$条边):

1.$n=2$且$m=1$(也就是两点一边),贡献为$k$

2.$n=m$(一个环),根据polya定理,贡献即$\frac{\sum_{i=0}^{n-1}k^{\gcd(n,i)}}{n}$

3.$n<m$,则任意两边的颜色都可以单独交换(其他边的颜色不变),即仅关心每种颜色的边的数量,根据插板法,贡献即${m+k-1\choose k-1}$

关于第3类中任意两边的颜色可以单独交换,下面来证明一下:

更方便的,由于整个连通,那么原结论等价于可以单独交换有公共端点的两条边

简单分析,可以发现这两条边必然会属于一个简单环$R_{1}$,且$R_{1}$与另一个简单环$R_{2}$有公共边

先通过在$R_{1}$上轮换,使得其中恰好有一条边属于公共边的部分,另一条边仅属于$R_{1}$

接下来,将这两条边单独交换,然后再轮换返回原来的位置

具体来说,先轮换$R_{2}$使得原本在公共边上的边仅属于$R_{2}$,再轮换$R_{1}$使得原本在$R_{1}$中的边在公共边上,再轮换$R_{1}$和$R_{2}$除去公共边的部分,可以发现就完成了交换

(更形象地,可以参考atcoder题解中第3页的4幅图)

时间复杂度为$o(n+m)$,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 55
4 #define mod 1000000007
5 struct Edge{
6 int nex,to;
7 }edge[N<<2];
8 stack<int>st;
9 vector<int>v[N];
10 int bcc,E,n,m,k,x,y,ans,head[N],dfn[N],low[N],vis[N];
11 int gcd(int x,int y){
12 if (!y)return x;
13 return gcd(y,x%y);
14 }
15 int pow(int n,int m){
16 int s=n,ans=1;
17 while (m){
18 if (m&1)ans=1LL*ans*s%mod;
19 s=1LL*s*s%mod;
20 m>>=1;
21 }
22 return ans;
23 }
24 void add(int x,int y){
25 edge[E].nex=head[x];
26 edge[E].to=y;
27 head[x]=E++;
28 }
29 void dfs(int k,int fa){
30 if (fa)st.push(k);
31 dfn[k]=low[k]=++dfn[0];
32 for(int i=head[k];i!=-1;i=edge[i].nex)
33 if (edge[i].to!=fa){
34 if (dfn[edge[i].to])low[k]=min(low[k],dfn[edge[i].to]);
35 else{
36 dfs(edge[i].to,k);
37 low[k]=min(low[k],low[edge[i].to]);
38 if (low[edge[i].to]>=dfn[k]){
39 while (1){
40 v[bcc].push_back(st.top());
41 st.pop();
42 if (v[bcc].back()==edge[i].to)break;
43 }
44 v[bcc++].push_back(k);
45 }
46 }
47 }
48 }
49 int main(){
50 scanf("%d%d%d",&n,&m,&k);
51 memset(head,-1,sizeof(head));
52 for(int i=1;i<=m;i++){
53 scanf("%d%d",&x,&y);
54 add(x,y);
55 add(y,x);
56 }
57 for(int i=1;i<=n;i++)
58 if (!dfn[i])dfs(i,0);
59 ans=1;
60 for(int i=0;i<bcc;i++){
61 int nn=v[i].size(),mm=0,s=0;
62 memset(vis,0,sizeof(vis));
63 for(int j=0;j<v[i].size();j++)vis[v[i][j]]=1;
64 for(int j=0;j<v[i].size();j++)
65 for(int k=head[v[i][j]];k!=-1;k=edge[k].nex)
66 if (vis[edge[k].to])mm++;
67 mm/=2;
68 if ((nn==2)&&(mm==1))s=k;
69 else{
70 if (nn==mm){
71 for(int j=0;j<nn;j++)s=(s+pow(k,gcd(nn,j)))%mod;
72 s=1LL*s*pow(nn,mod-2)%mod;
73 }
74 else{
75 s=1;
76 for(int j=mm+1;j<mm+k;j++)s=1LL*s*j%mod;
77 for(int j=1;j<k;j++)s=1LL*s*pow(j,mod-2)%mod;
78 }
79 }
80 ans=1LL*ans*s%mod;
81 }
82 printf("%d",ans);
83 }

[atARC062F]Painting Graphs with AtCoDeer的更多相关文章

  1. [Arc062] Painting Graphs with AtCoDeer

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

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

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

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

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

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

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

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

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

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

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

  7. [ARC062F]Painting Graphs with AtCoDeer

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

  8. 【ARC062F】 Painting Graphs with AtCoDeer 点双连通分量+polya定理

    Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色. 你可以对一张染色了的图进行若干次操作,每次操作形如,在图中选择一个简单环(即不经过相同点的环),并且将其颜色逆时针 ...

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

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

随机推荐

  1. Bert文本分类实践(一):实现一个简单的分类模型

    写在前面 文本分类是nlp中一个非常重要的任务,也是非常适合入坑nlp的第一个完整项目.虽然文本分类看似简单,但里面的门道好多好多,作者水平有限,只能将平时用到的方法和trick在此做个记录和分享,希 ...

  2. 硝烟中的Scrum和XP

    硝烟中的Scrum和XP 初次接触Scrum和XP(更加准确的说是"看到"),心里不免有些疑问,软件开发为什么会有如此多的方式,难道软件开发.软件工程不就是写写代码的事儿吗?直到后 ...

  3. JVM堆内存泄露分析

      一.背景 公司有一个中间的系统A可以对接多个后端业务系统B,一个业务系统以一个Namespace代表, Namespace中包含多个FrameChannel(用holder保存),表示A连接到业务 ...

  4. Oracle12C安装教程

    准备工作 网盘链接: https://pan.baidu.com/s/1gffHbOjImk1SfezdWO2Bpw 提取码: imft Oracle12C的安装 1.分别解压"winx64 ...

  5. FastAPI 学习之路(三十二)创建数据库

    在大型的web开发中,我们肯定会用到数据库操作,那么FastAPI也支持数据库的开发,你可以用 PostgreSQL MySQL SQLite Oracle 等 本文用SQLite为例.我们看下在fa ...

  6. 保护模式篇——TLB与CPU缓存

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  7. canvas中的优先级,.after最前,before最底,canvas中间,部件在布局下面

    <RelativeWidget>: # 画布之后 canvas.before: Color: # 白色 rgba:[1,1,1,1] Rectangle: pos:self.pos # 最 ...

  8. STM32串口通信配置(USART1+USART2+USART3+UART4) (转)

    一.串口一的配置(初始化+中断配置+中断接收函数) 1 /*====================================================================== ...

  9. hdu 1080 Human Gene Functions(DP)

    题意: 人类基因由A.C.G.T组成. 有一张5*5的基因表.每格有一个值,叫相似度.例:A-C:-3.意思是如果A和C配对, 则它俩的相似度是-3[P.S.:-和-没有相似度,即-和-不能配对] 现 ...

  10. C++中gSOAP的使用

    目录 SOAP简介 gSOAP 准备工作 头文件 构建客户端应用程序 生成soap源码 建立客户端项目 构建服务端应用程序 生成SOAP源码 建立服务端项目 打印报文 SOAP测试 项目源码 本文主要 ...