ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)
似乎好久都没写博客了....赶快来补一篇
题意
给你一个 \(n\) 个点 , 没有重边和自环的图 .
有 \(m\) 条边 , 每条边可以染 \(1 \to k\) 中的一种颜色 .
对于任意一个简单环 , 可以将它的边的颜色进行旋转任意位 .
询问本质不同的染色方案数个数 .
数据范围
\(1\le n \le 50, 1 \le m \le 100,1 \le k \le 100\\\)
题解
将边 (或者说是很多条边) 分为 \(3\) 种类型 :
- 不属于任何一个简单环 , 它的贡献为 \(k\) . 
- 属于且仅属于一个简单环 (除了环上的边没边了) , 设环长为 \(n\) . 它的贡献就是 
\]
这个就是类似于项链染色的方案数求解 , 原因见 此篇博客 .
- 属于多个环 (或者说是构成了的环 , 除了环上的边还有其他边) . 能够证明可以通过旋转来交换任意两条边的颜色 . 
 于是本质不同当且仅当有一种颜色数量不同 , 那计算的话 , 就是利用隔板法 把 \(m\) 条边 分成 \(k\) 组的方案数 (每组不一定要有边)- 那么我们肖就加入多的 \(k - 1\) 个隔板 , 然后贡献很显然就是$${n + k - 1 \choose k - 1}$$ 
这个全都可以利用 \(Tarjan\) 求点双联通分量 (求割点的方法) 来判断种类 , 并在其中计算 , 把所有贡献乘起来就是最后的答案了.
时间复杂度就是 \(O(n+m)\) 轻松通过此题.
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
    int x = 0, fh = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar() ) if (ch == '-') fh = -1;
    for (; isdigit(ch); ch = getchar() ) x = (x << 1) + (x << 3) + (ch ^ '0');
    return x * fh;
}
void File() {
#ifdef zjp_shadow
	freopen ("F.in", "r", stdin);
	freopen ("F.out", "w", stdout);
#endif
}
const int N = 55, M = 205;
typedef long long ll;
const ll Mod = 1e9 + 7;
ll fpm(ll x, int power) {
	ll res = 1;
	for (; power; power >>= 1, (x *= x) %= Mod)
		if (power & 1) (res *= x) %= Mod;
	return res;
}
ll fac[M], ifac[M];
void Init(int maxn) {
	fac[0] = ifac[0] = 1ll;
	For (i, 1, maxn) fac[i] = fac[i - 1] * i % Mod;
	ifac[maxn] = fpm(fac[maxn], Mod - 2);
	Fordown (i, maxn - 1, 1) ifac[i] = ifac[i + 1] * (i + 1) % Mod;
}
ll C(int m, int n) {
	if (m > n || n < 0 || m < 0) return 0ll;
	return fac[n] * ifac[m] % Mod * ifac[n - m] % Mod;
}
set <int> Point;
int n, m, k; ll ans = 1ll;
ll Polya(int n) {
	ll res = 0;
	For (i, 1, n) (res += fpm(k, __gcd(n, i))) %= Mod;
	return res * fpm(n, Mod - 2) % Mod;
}
ll Permu(int m) { return C(k - 1, m + k - 1); }
vector<int> G[N];
int dfn[N], lowlink[N], sta[N], top;
void Tarjan(int u, int fa) {
	static int clk = 0;
	dfn[u] = lowlink[u] = (++ clk); sta[++ top] = u;
	for (int v : G[u]) if (!dfn[v]) {
		Tarjan(v, u), chkmin(lowlink[u], lowlink[v]);
		if (lowlink[v] >= dfn[u]) {
			Point.clear();
			int n = 0, m = 0, Last;
			do Point.insert(Last = sta[top --]), ++ n; while (Last != v);
			Point.insert(u), ++ n;
			for (int x : Point) for (int v : G[x])
				if ((bool)Point.count(v)) ++ m;
			m >>= 1;
			if (m < n) (ans *= k) %= Mod;
			if (m == n) (ans *= Polya(n)) %= Mod;
			if (m > n) (ans *= Permu(m)) %= Mod;
		}
	} else chkmin(lowlink[u], dfn[v]);
	if (!fa) -- top;
}
int main () {
	File();
	n = read(), m = read(); k = read();
	Init(m + k + 5);
	For (i, 1, m) {
		int u = read(), v = read();
		G[u].push_back(v);
		G[v].push_back(u);
	}
	For (i, 1, n) if (!dfn[i]) Tarjan(i, 0);
	printf ("%lld\n", ans);
    return 0;
}
ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)的更多相关文章
- ARC 062 F - Painting Graphs with AtCoDeer 割点 割边 不动点 burnside引理
		LINK:Painting Graphs with AtCoDeer 看英文题面果然有点吃不消 一些细节会被忽略掉. 问每条边都要被染色 且一个环上边的颜色可以旋转. 用c种颜色有多少本质不同的方法. ... 
- [Arc062] Painting Graphs with AtCoDeer
		[Arc062] Painting Graphs with AtCoDeer Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色.你可以对一张染色了的图进行若干次操作, ... 
- 【ARC062F】 Painting Graphs with AtCoDeer 点双连通分量+polya定理
		Description 给定一张N点M边的无向图,每条边要染一个编号在1到K的颜色. 你可以对一张染色了的图进行若干次操作,每次操作形如,在图中选择一个简单环(即不经过相同点的环),并且将其颜色逆时针 ... 
- 2018.09.20 atcoder Painting Graphs with AtCoDeer(tarjan+polya)
		传送门 一道思维题. 如果没有环那么对答案有k的贡献. 如果恰为一个环,可以用polya求贡献. 如果是一个有多个环重叠的双联通的话,直接转化为组合数问题(可以证明只要每种颜色被选取的次数相同一定可以 ... 
- AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】
		题目分析: 如果一个双连通分量是简单环,那么用polya原理计数循环移位即可. 如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换. 如果一条边是桥,那么直接乘以k ... 
- 【AtCoder】ARC062F - AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer
		题解 考虑一个点双(因为是简单环),如果没有环(两点一线),那么乘上K 如果有一个环,那么用polya定理,每个置换圈有gcd(i,n)个循环节 如果有两个及以上的环,任何一种置换都合法,那么只和每个 ... 
- ARC062F AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer  Burnside 引理
		题目传送门 https://atcoder.jp/contests/arc062/tasks/arc062_d 题解 首先对整张图做 Tarjan 点双. 对于一个点双,如果是由一条边构成的,那么很显 ... 
- [ARC062F]Painting Graphs with AtCoDeer
		题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ... 
- [atARC062F]Painting Graphs with AtCoDeer
		求出点双后缩点,对于点双之间,显然不存在简单环,即每一个简单环一定在一个点双内部,换言之即每一个点双可以独立的考虑,然后将结果相乘 (对于点双之间的边任意染色,即若有$s$条边,还会有$k^{s}$的 ... 
随机推荐
- JS-JS创建数组的三种方法
			隐式创建 var arr=["Audi","BMW","Volvo"]; 直接实例化 var arr=new Array("Aud ... 
- 查看MS Sqlserver文件大小语句
			1..查询数据库的数据文件及日志文件的相关信息(包括文件组.当前文件大小.文件最大值.文件增长设置.文件逻辑名.文件路径等) select * from [数据库名].[dbo].[sysfiles] ... 
- 锁、C#中Monitor和Lock以及区别
			1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁 ... 
- CF [2016-2017 ACM-ICPC CHINA-Final][GYM 101194 H] Great Cells
			很久以前做的一道思博题了,今天来补一补. 大致题意:在一个\(n*m\)的矩阵内填整数,数字在\([1,k]\)范围内.矩阵中某格的数为great number当且仅当与它同行同列的数字都严格比它小. ... 
- 在Windows7上如何找到Cookie
			摘要 出于兴趣爱好,前一阵子做了一个网页,网页中需要用到Cookie,但是,根据书上的说明,并没有找打教材中所说的Cookie的位置,本文就主要介绍在计算机(Win7)中Cookie的存放位置,同样适 ... 
- FFMPEG指令
			FFmpeg是一个用于音视频处理的自由软件,被广泛用于音视频开发.FFmpeg功能强大,本文主要介绍如何使用FFmpeg命令行工具进行简单的视频处理. 安装FFmpeg可以在官网下载各平台软件包或者静 ... 
- Haproxy基础知识 -运维小结
			开源软件负载均衡器 现在常用的三大开源软件负载均衡器分别是Nginx.LVS.Haproxy. 在之前的文章中已经对比了这三个负载均衡软件, 下面根据自己的理解和使用经验, 再简单说下这三个负载均衡软 ... 
- 个人阅读作业——软件工程M1/M2的总结
			临近学期末,本学期的软件工程课也已经结束了,在此我对软件工程课中,我们团队M1和M2开发阶段中,我做的工作做一个总结 我是DEV,主要工作是等着上级给我分配任务,但是很多时候如果这个活我不干,其他人就 ... 
- BugPhobia发布篇章:学霸在线系统测试报告
			0x00 :测试报告版本管理 版本号 具体细节 修订时间 V 1.0 整理第一轮迭代用户管理和登陆注册的功能性验证测试,预计将继续网页对浏览器版本的兼容性测试 2015/11/12 V1.0.1 整理 ... 
- 安装mysql解压版时遇到的错误
			平常都是使用exe安装mysql,今天使用解压包的,遇到了一系列问题: 环境:win10 mysql版本:mysql-5.7.21-winx64 开始一直用该网页的教程 https://www.cnb ... 
