题目分析:

如果一个双连通分量是简单环,那么用polya原理计数循环移位即可。

如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换。

如果一条边是桥,那么直接乘以k就行了。

代码:

 #include<bits/stdc++.h>
using namespace std; const int mod = ;
const int maxn = ; int n,m,k;
vector <int> g[maxn]; int fa[maxn],arr[maxn],dfn[maxn],bccnum,low[maxn],cl; vector <pair<int,int> > bcc[maxn];
vector <int> hhh[maxn]; void read(){
scanf("%d%d%d",&n,&m,&k);
for(register int i=;i<=m;i++){
int u,v; scanf("%d%d",&u,&v);
g[u].push_back(v); g[v].push_back(u);
}
} stack<int> sta;
void Tarjan(int now,int f){
fa[now] = f;
low[now] = dfn[now] = ++cl;
sta.push(now);
for(int i=;i<g[now].size();i++){
if(g[now][i] == f) continue;
if(dfn[g[now][i]] > dfn[now]) continue;
if(!dfn[g[now][i]]){
Tarjan(g[now][i],now);
low[now] = min(low[now],low[g[now][i]]);
}else{
low[now] = min(low[now],dfn[g[now][i]]);
hhh[now].push_back(g[now][i]);
}
}
if(f == || low[now] >= dfn[fa[now]]){
bccnum++;
while(true){
int k = sta.top();sta.pop();
arr[k] = ;
if(fa[k] == ) break;
bcc[bccnum].push_back(make_pair(k,fa[k]));
for(int i=;i<hhh[k].size();i++){
bcc[bccnum].push_back(make_pair(k,hhh[k][i]));
}
if(k == now) break;
}
if(bcc[bccnum].size() == ) bccnum--;
}
} int C[maxn*][maxn*]; int fast_pow(int now,int pw){
int ans = ,dt = now, bit = ;
while(bit <= pw){
if(bit & pw){ans =1ll*ans*dt%mod;}
dt = 1ll*dt*dt%mod; bit<<=;
}
return ans;
} int solve(int now){
int ans = ;
for(register int i=;i<=now;i++){
ans += fast_pow(k,__gcd(now,i));
ans %= mod;
}
ans = 1ll*ans*fast_pow(now,mod-)%mod;
return ans;
} int hap[maxn];
void work(){
for(register int i=;i<=n;i++){
if(arr[i]) continue;
Tarjan(i,);
}
C[][] = ;
for(register int i=;i<=;i++){
C[i][] = C[i][i] = ;
for(register int j=;j<i;j++){
C[i][j] = (C[i-][j] + C[i-][j-])%mod;
}
}
int ans = ;
for(register int i=;i<=bccnum;i++){
int flag = ;
for(register int j=;j<bcc[i].size();j++){
if(hap[bcc[i][j].first] && hap[bcc[i][j].second]) flag--;
hap[bcc[i][j].first]++; hap[bcc[i][j].second]++;
}
for(register int j=;j<bcc[i].size();j++){
hap[bcc[i][j].first]--; hap[bcc[i][j].second]--;
}
if(flag == || flag == ){
if(bcc[i].size() == ) ans = 1ll*ans*k%mod;
else ans = 1ll*ans*solve(bcc[i].size())%mod;
}else{
ans = 1ll*ans*C[bcc[i].size()+k-][k-]%mod;
}
}
printf("%d",ans);
} int main(){
read();
work();
return ;
}

AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】的更多相关文章

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

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

  2. [Arc062] Painting Graphs with AtCoDeer

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

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

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

  4. HohoCoder 1184 : 连通性二·边的双连通分量(+原理证明)

    1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老师 ...

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

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

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

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

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

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

  8. [atARC062F]Painting Graphs with AtCoDeer

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

  9. [ARC062F]Painting Graphs with AtCoDeer

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

随机推荐

  1. 一点感悟:《Node.js学习笔记》star数突破1000+

    写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...

  2. H5 文字属性

    03-文字属性 我是文字 我是文字 abc我是段落 <!DOCTYPE html> <html lang="en"> <head> <me ...

  3. Linux进程与线程的区别

    进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念, ...

  4. c++入门之——const在函数名前面和函数后面的区别

    class Test(){ public: Test(){} const int foo(int a); const int foo(int a) const; }; 一.概念 当const在函数名前 ...

  5. iOS使用XZMRefresh实现UITableView或UICollectionView横向刷新

    https://blog.csdn.net/u013285730/article/details/50615551?utm_source=blogxgwz6 XZMRefresh The easies ...

  6. javac与java版本不一致

    项目测试时遇到该问题,因为loadRunner不支持jdk1.7,但运行java脚本时提示jdk版本是1.7,实际的JAVA_HOME设置为1.6. 运行javac -version与java -ve ...

  7. js刷新界面前事件onbeforeunload

    这个方法的作用是防止填写信息时不小心按了刷新(F5,刷新界面,返回). 目前能实现这个需求的只有这个方法. 具体代码如下: 1.首先在body添加 onbeforeunload 这个事件 <bo ...

  8. Oracle 用户管理与权限分配

    用户管理是系统管理员最基本的任务之一,用户想要连接数据库并且使用相应的系统资源就必须是系统的合法用户且具有对应的权限. 1 创建用户 default tablespace default_tables ...

  9. 剑指offer(13)

    题目: 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 思路: 判断当前两个根结点是否相等,如果相等,判断左右子树是否相等,如果不依次判断左右子树是否满足上 ...

  10. zepto的extend

    类型判断 var class2type = {},toString = class2type.toString,$={}; //判断类型 function type(obj) { return obj ...