题意:

平面上给出一个\(N\)个点\(M\)条边的无向图,要用\(C\)种颜色去给每个顶点染色。

如果一种染色方案可以旋转得到另一种染色方案,那么说明这两种染色方案是等价的。

求所有染色方案数 \(mod \: 10^9+7\)

分析:

这种等价类计数的问题可以用Polya定理来解决。

首先这个图形要想能旋转,本身必须中心对称,即旋转以后的顶点要和原图完全重合,一一对应。

事实上,旋转的角度只能是\(90^{\circ}\)的整数倍。

因为给出来的点都是整点,求出来的对称中心的坐标也都是有理数。如果再旋转更小的角度的话(比如\(60^{\circ}\)),就一定会出现无理数的坐标,所以这是不可能的。

所以只会有一下三种情况:

  • 图本身不对称,置换群只有一个恒等置换
  • 图是中心对称,置换群有两个置换:恒等置换 和 逆时针旋转\(180^{\circ}\)
  • 图不仅是中心对称,而且可以旋转\(90^{\circ}\),则置换群有四个置换:恒等置换 逆时针旋转\(90^{\circ}\) 逆时针旋转\(180^{\circ}\) 和 逆时针旋转\(270^{\circ}\)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#define MP make_pair
using namespace std; typedef pair<int, int> PII;
typedef long long LL;
const int maxn = 50 + 10;
const double eps = 1e-8;
const LL MOD = 1000000007; void add_mod(LL& a, LL b) {
a += b; if(a >= MOD) a -= MOD;
} LL pow_mod(LL a, int n) {
LL ans = 1LL;
while(n) {
if(n & 1) ans = ans * a % MOD;
a = a * a % MOD;
n >>= 1;
}
return ans;
} LL Inverse(LL a) { return pow_mod(a, MOD - 2); } int dcmp(double x) {
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
} struct Point
{
double x, y;
Point(double x = 0, double y = 0):x(x), y(y) {}
void read() { scanf("%lf%lf", &x, &y); }
}; typedef Point Vector; Point operator + (const Point& A, const Point& B) {
return Point(A.x + B.x, A.y + B.y);
} Point operator - (const Point& A, const Point& B) {
return Point(A.x - B.x, A.y - B.y);
} Point operator * (const Point& A, double p) {
return Point(A.x * p, A.y * p);
} Point operator / (const Point& A, double p) {
return Point(A.x / p, A.y / p);
} bool operator == (const Point& A, const Point& B) {
return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;
} int n, m, c;
Point p[maxn], center;
bool G[maxn][maxn];
PII edges[maxn * maxn]; Point Rotate(Point P, int n) {
if(n == 0) return P;
Vector v = P - center;
if(n == 1) return center + Vector(-v.y, v.x);
if(n == 2) return center + Vector(-v.x, -v.y);
if(n == 3) return center + Vector(v.y, -v.x);
} int Findit(Point q) {
for(int i = 1; i <= n; i++)
if(p[i] == q) return i;
return 0;
} int t[maxn];
bool vis[maxn]; bool RotateGraph(int x) {
for(int i = 1; i <= n; i++) {
t[i] = Findit(Rotate(p[i], x));
if(t[i] == 0) return false;
}
for(int i = 0; i < m; i++) {
int u = edges[i].first, v = edges[i].second;
if(!G[t[u]][t[v]]) return false;
}
return true;
} int Cycle() {
memset(vis, false, sizeof(vis));
int ans = 0;
for(int i = 1; i <= n; i++) if(!vis[i]) {
ans++;
vis[i] = true;
for(int s = t[i]; s != i; s = t[s]) {
vis[s] = true;
}
}
return ans;
} int main() {
//freopen("7056.txt", "r", stdin); LL inv_2 = Inverse(2), inv_4 = Inverse(4); int T; scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &n, &m, &c);
center = Point(0, 0); for(int i = 1; i <= n; i++) {
p[i].read();
center = center + p[i];
}
center = center / n; memset(G, false, sizeof(G));
for(int u, v, i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
edges[i] = MP(u, v);
G[u][v] = G[v][u] = true;
} LL ans = pow_mod(c, n) % MOD;
if(!RotateGraph(2)) { printf("%lld\n", ans); continue; } int k = Cycle();
add_mod(ans, pow_mod(c, k)); if(!RotateGraph(1)) {
ans = ans * inv_2 % MOD;
printf("%lld\n", ans);
continue;
} k = Cycle();
add_mod(ans, (pow_mod(c, k) * 2) % MOD);
ans = ans * inv_4 % MOD;
printf("%lld\n", ans);
} return 0;
}

LA 7056 Colorful Toy Polya定理的更多相关文章

  1. 【转】Polya定理

    转自:http://endlesscount.blog.163.com/blog/static/82119787201221324524202/ Polya定理 首先记Sn为有前n个正整数组成的集合, ...

  2. 【群论】polya定理

    对Polya定理的个人认识     我们先来看一道经典题目:     He's Circles(SGU 294)         有一个长度为N的环,上面写着“X”和“E”,问本质不同的环有多少个(不 ...

  3. [wikioi2926][AHOI2002]黑白瓷砖(Polya定理)

    小可可在课余的时候受美术老师的委派从事一项漆绘瓷砖的任务.首先把n(n+1)/2块正六边形瓷砖拼成三角形的形状,右图给出了n=3时拼成的“瓷砖三角形”.然后把每一块瓷砖漆成纯白色或者纯黑色,而且每块瓷 ...

  4. HDU 3923 Invoker(polya定理+逆元)

    Invoker Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 122768/62768 K (Java/Others)Total Su ...

  5. Polya定理

    http://www.cnblogs.com/wenruo/p/5304698.html 先看 Polya定理,Burnside引理回忆一下基础知识.总结的很棒. 一个置换就是集合到自身的一个双射,置 ...

  6. POJ 2409 Let it Bead(Polya定理)

    点我看题目 题意 :给你c种颜色的n个珠子,问你可以组成多少种形式. 思路 :polya定理的应用,与1286差不多一样,代码一改就可以交....POJ 1286题解 #include <std ...

  7. POJ 1286 Necklace of Beads(Polya定理)

    点我看题目 题意 :给你3个颜色的n个珠子,能组成多少不同形式的项链. 思路 :这个题分类就是polya定理,这个定理看起来真的是很麻烦啊T_T.......看了有个人写的不错: Polya定理: ( ...

  8. 百练_2409 Let it Bead(Polya定理)

    描述 "Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you ca ...

  9. polya定理小结

    polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题. 当项链旋转时有n种置换,循环节的个数分别是gcd(n, i); 当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个 ...

随机推荐

  1. SQL server下所有表名及字段名及注释查询

    --查询所有表及注释SELECTA.name ,C.valueFROM sys.tables A LEFT JOIN sys.extended_properties C ON C.major_id = ...

  2. 关于死循环while(true){}或for(;;){}的总结

    关于死循环while(true){}或for(;;){}的总结 1.基本用法: while(true){     语句体; } for(;;){     语句体; } 以上情况,语句体会一直执行. 2 ...

  3. PLSQL Developer 12 保存登录的用户名和密码

    1. 登录 PLSQL Developer PLSQL Developer > Preferences 2. Preferences > Logon History > Defini ...

  4. django之母版的继承

    模板继承示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  5. ApexSQL Log中的Redo Script跟原始SQL不一致问题

    最近遇到一个误更新数据的问题,使用ApexSQL Log做挖掘事务日志的时候,发现ApexSQL Log生成的Redo Script跟原始SQL是有区别的.它们并不是完全一致的.只是逻辑上等价而已.如 ...

  6. Azure 镜像市场支持一键部署到云

    本视频教程介绍了Azure 镜像市场和一键部署到云. Azure 镜像市场(AMP)由世纪互联运营,是一个联机应用程序和服务市场,它通过独立软件服务商(ISV)能够成为 Azure 客户(Custom ...

  7. SC || Chapter 8

    栈:方法调用和局部变量的存储位置,保存基本类型 堆:在一块内存里分为多个小块,每块包含 一个对象,或者未被占用

  8. Nuget使用备忘

    菜单:工具-库程序包管理器-管理解决方案的NuGet程序包,搜索,下载,安装 或者 工具-库程序包管理器-程序包管理器控制台,输入PM命令,如: install-package log4net 如果不 ...

  9. Linux连接外网

    1.给linux配置ip 进行远程管理 如果网络不同的话需要配置网卡,命令如下: vi /etc/sysconfig/network-scripts/ifcfg-enp0s3   回车 就出现网络的环 ...

  10. 远程连接 mySql数据库

    远程连接 mySql数据库 一.安装并配置MySQL1.安装MySQL:运行mysql-essential-6.0.11-alpha-win32,按“MySQL+6.0+Windows下安装图解”完成 ...