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

(对于点双之间的边任意染色,即若有$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. windows下编译caffe出现错误 C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe?

    解决方案来自http://blog.csdn.net/u012556077/article/details/50353818

  2. 统计学习:线性支持向量机(SVM)

    学习策略 软间隔最大化 上一章我们所定义的"线性可分支持向量机"要求训练数据是线性可分的.然而在实际中,训练数据往往包括异常值(outlier),故而常是线性不可分的.这就要求我们 ...

  3. CSS常见的5种垂直水平居中(面试够用)

    方法一 (flex) <div id='box'> <div class='child'></div> </div> #box{ width:200px ...

  4. 洛谷4172 WC2006水管局长(LCT维护最小生成树)

    这个题和魔法森林感觉有很相近的地方啊 同样也是维护一个类似最大边权最小的生成树 但是不同的是,这个题是有\(cut\)和询问,两种操作.... 这可如何是好啊? 我们不妨倒着来考虑,假设所有要\(cu ...

  5. zabbix和prometheus的优缺点对比

    使用Prometheus(https://github.com/prometheus)原生的k8s服务发现驱动,采集容器化信息:通过微服务参数配置,暴露运行状态信息提供给prometheus,实现微服 ...

  6. 手把手教你学Dapr - 1. .Net开发者的大时代

    Dapr全称 Distributed Application Runtime,分布式应用运行时 Dapr的口号 简化云原生应用开发,聚焦在应用的核心逻辑,让代码简单.可移植 Dapr的目标 最佳实践的 ...

  7. vue3.x自定义组件双向数据绑定v-model

    vue2.x 语法 在 2.x 中,在组件上使用 v-model 相当于绑定 value prop 并触发 input 事件: <ChildComponent v-model="pag ...

  8. gridlayout在kv中的引用

    from kivy.app import App from kivy.uix.gridlayout import GridLayout class GridLayoutWidget(GridLayou ...

  9. 2021北航敏捷软工Beta阶段评分与总结

    概述 Beta 阶段评分,按照之前的规则,主要组成部分为: 博客部分,基于 Beta 阶段博客的评分(每篇正规博客 10 分,每篇 Scrum5 分,评定方式类比往年) 评审部分,基于 Beta 阶段 ...

  10. c#复制数组的多种方法

    方法一:使用for循环 int []pins = {9,3,7,2} int []copy = new int[pins.length]; for(int i =0;i!=copy.length;i+ ...