[atARC062F]Painting Graphs with AtCoDeer
求出点双后缩点,对于点双之间,显然不存在简单环,即每一个简单环一定在一个点双内部,换言之即每一个点双可以独立的考虑,然后将结果相乘
(对于点双之间的边任意染色,即若有$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的更多相关文章
- [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种颜色有多少本质不同的方法. ...
- AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】
题目分析: 如果一个双连通分量是简单环,那么用polya原理计数循环移位即可. 如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换. 如果一条边是桥,那么直接乘以k ...
- ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)
似乎好久都没写博客了....赶快来补一篇 题意 给你一个 \(n\) 个点 , 没有重边和自环的图 . 有 \(m\) 条边 , 每条边可以染 \(1 \to k\) 中的一种颜色 . 对于任意一个简 ...
- 2018.09.20 atcoder Painting Graphs with AtCoDeer(tarjan+polya)
传送门 一道思维题. 如果没有环那么对答案有k的贡献. 如果恰为一个环,可以用polya求贡献. 如果是一个有多个环重叠的双联通的话,直接转化为组合数问题(可以证明只要每种颜色被选取的次数相同一定可以 ...
- 【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer
题解 考虑一个点双(因为是简单环),如果没有环(两点一线),那么乘上K 如果有一个环,那么用polya定理,每个置换圈有gcd(i,n)个循环节 如果有两个及以上的环,任何一种置换都合法,那么只和每个 ...
- [ARC062F]Painting Graphs with AtCoDeer
题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...
- 【ARC062F】 Painting Graphs with AtCoDeer 点双连通分量+polya定理
Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色. 你可以对一张染色了的图进行若干次操作,每次操作形如,在图中选择一个简单环(即不经过相同点的环),并且将其颜色逆时针 ...
- ARC062F AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer Burnside 引理
题目传送门 https://atcoder.jp/contests/arc062/tasks/arc062_d 题解 首先对整张图做 Tarjan 点双. 对于一个点双,如果是由一条边构成的,那么很显 ...
随机推荐
- JVM堆内存泄露分析
一.背景 公司有一个中间的系统A可以对接多个后端业务系统B,一个业务系统以一个Namespace代表, Namespace中包含多个FrameChannel(用holder保存),表示A连接到业务 ...
- Hadoop面试题总结(三)——MapReduce
1.谈谈Hadoop序列化和反序列化及自定义bean对象实现序列化? 1)序列化和反序列化 (1)序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输. (2) ...
- 2020.11.14-pta天梯练习赛补题
7-7 矩阵A乘以B 给定两个矩阵A和B,要求你计算它们的乘积矩阵AB.需要注意的是,只有规模匹配的矩阵才可以相乘.即若A有Ra行.Ca列,B有Rb行.Cb列,则只有Ca ...
- Spark RDD编程(博客索引,日常更新)
本篇主要是记录自己在中解决RDD编程性能问题中查阅的论文博客,为我认为写的不错的建立索引方便查阅,我的总结会另立他篇 1)通过分区(Partitioning)提高spark性能https://blog ...
- django通过管理页上传图片
1.配置目录 新建上传录.static/medis 2.设置上传文件保存路径 # setting.py中设置上传文件路径static/media MEDIA_ROOT = os.path.join(B ...
- LeetCode:树专题
树专题 参考了力扣加加对与树专题的讲解,刷了些 leetcode 题,在此做一些记录,不然没几天就没印象了 力扣加加-树专题 总结 树的定义 // Definition for a binary tr ...
- Beta实际开发与初始计划的比较
零.说明 本篇博客为Beta阶段开始十天后,实际开发工作与初始计划的比较 截止至本篇博客发布为止,团队所有成员已完成计网考试,将在本周日进行充分的接口测试 一.比较 1.与初始计划对比 初始计划 实际 ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- linux基本命令二
组管理与权限管理 文件/目录所有者 修改文件所有者 chown 用户名 文件名 创建文件所在组 groupadd 修改文件所在组 chgrp 组名 文件名 其他组:除文件的所有者和所在组的用 ...
- 30分钟通过Kong实现.NET网关
什么是Kong Openrestry是一个基于Nginx与Lua的高性能平台,内部有大量的Lua库.其中ngx_lua_moudule使开发人员能使用Lua脚本调用Nginx模块.Kong是一个Ope ...