抽象后的题意:给一个不超过30个点的图,A从中选不超过5个点涂红绿两种颜色,B用黑白两种颜色把剩下的涂完,任意一条边两端的颜色不同,求每种颜色至少用涂一次的方案数

思路:枚举A涂的点的集合,将原图分成两个子图P和Q,P和Q互相不影响,因为涂的颜色不同。考虑A在P中涂颜色,由于一条边的两端的颜色不能相同,于是对P进行二分染色,如果是非二分图,那么方案数为0,否则令P的连通分量个数为cnt,如果点集小于2则方案总数为0,否则如果边数为0,说明给P涂1种颜色的答案为2,最后答案为2cnt-2,边数不为0则答案为2cnt。Q与P同理。

#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fillarray(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; #ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const double EPS = 1e-12; /* -------------------------------------------------------------------------------- */ const int maxn = ; int n, m; struct Ufs {
int fa[maxn];
void init() { for (int i = ; i < maxn; i ++) fa[i] = i; }
int getfa(int u) { return u == fa[u]? u : fa[u] = getfa(fa[u]); }
int add(int u, int v) { fa[getfa(u)] = getfa(v); }
};
Ufs ufs; inline int makeid(int x, int y) {
return x * m + y;
} bool e[][];
int newnode[maxn];
int c; ll ans = ; bool E[][];
int vis[]; bool dfs(int u, int c, int color) {
vis[u] = color;
for (int i = ; i < c; i ++) {
if (E[u][i]) {
if (!vis[i]) if (!dfs(i, c, - color)) return false;
if (vis[i] == vis[u]) return false;
}
}
return true;
} int count(bool sube[][], int c) {
int ans = ;
fillchar(vis, );
for (int i = ; i < c; i ++) {
for (int j = ; j < c; j ++) {
E[i][j] = sube[i][j];
}
}
for (int i = ; i < c; i ++) {
if (!vis[i]) {
ans ++;
if (!dfs(i, c, )) return - INF;
}
}
return ans;
} int useonecolor(bool sube[][], int c) {
for (int i = ; i < c; i ++) {
for (int j = ; j < c; j ++) {
if (sube[i][j]) return ;
}
}
if (c) return ;
return ;
} int s[], top = ; void dfs(int p, int r) {
if (r == ) {
int rst[], extra[];
int t = ;
bool vis[] = {}, sube[][] = {}, sube2[][] = {};
for (int i = ; i < top; i ++) {
rst[i] = s[i];
vis[s[i]] = true;
}
for (int i = ; i < c; i ++) {
if (!vis[i]) extra[t ++] = i;
}
for (int j = ; j < top; j ++) {
for (int k = ; k < top; k ++) {
sube[j][k] = e[rst[j]][rst[k]];
}
}
for (int j = ; j < c - top; j ++) {
for (int k = ; k < c - top; k ++) {
sube2[j][k] = e[extra[j]][extra[k]];
}
}
ll girl = count(sube, top), boy = count(sube2, c - top);
if (girl < || boy < ) return ;
girl = << girl;
boy = << boy;
ans += (girl - useonecolor(sube, top)) * (boy - useonecolor(sube2, c - top));
return ;
}
for (int i = p; i <= c - r; i ++) {
s[top ++] = i;
dfs(i + , r - );
top --;
}
} char str[][]; int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int cas = ;
while (cin >> n >> m) {
ufs.init();
for (int i = ; i < n; i ++) {
scanf("%s", str[i]);
for (int j = ; str[i][j]; j ++) {
if (j && str[i][j] == str[i][j - ]) ufs.add(makeid(i, j), makeid(i, j - ));
if (i && str[i][j] == str[i - ][j]) ufs.add(makeid(i, j), makeid(i - , j));
}
}
c = ;
for (int i = ; i < n; i ++) {
for (int j = ; j < m; j ++) {
if (ufs.getfa(makeid(i, j)) == makeid(i, j)) newnode[makeid(i, j)] = c ++;
}
}
fillchar(e, );
for (int i = ; i < n; i ++) {
for (int j = ; j < m; j ++) {
if (i && str[i][j] != str[i - ][j]) e[newnode[ufs.getfa(makeid(i, j))]][newnode[ufs.getfa(makeid(i - , j))]] = true;
if (j && str[i][j] != str[i][j - ]) e[newnode[ufs.getfa(makeid(i, j))]][newnode[ufs.getfa(makeid(i, j - ))]] = true;
}
}
for (int i = ; i < c; i ++) {
for (int j = ; j < c; j ++) {
e[i][j] = e[i][j] || e[j][i];
}
//print(e[i], e[i] + c);
}
ans = ;
for (int i = ; i <= min(, c); i ++) dfs(, i);
printf("Case %d: ", ++ cas);
cout << ans << endl;
}
return ;
}

[csu1508 地图的四着色]二分图染色的更多相关文章

  1. CSU 1508:地图的四着色(DFS+剪枝)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1508 题意:地图中四联通的块是一个国家,A和B每个人可以涂两种颜色,且B不能涂超过5次,相邻的国家 ...

  2. UVA-10004-Bicoloring二分图染色

    题意:给一张图,判断是不是二分图: 自己一开始不知道是二分图染色,理解的是任意三点不能互相连接 可能以后遇到这样的模型,可以往二分图想: 首先怎么判定一个图是否为二分图 从其中一个定点开始,将跟它邻接 ...

  3. NOIP2008双栈排序[二分图染色|栈|DP]

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  4. 洛谷P1330封锁阳光大学[二分图染色]

    题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M ...

  5. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  6. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

  7. Codeforces Round #311 (Div. 2) D - Vitaly and Cycle(二分图染色应用)

    http://www.cnblogs.com/wenruo/p/4959509.html 给一个图(不一定是连通图,无重边和自环),求练成一个长度为奇数的环最小需要加几条边,和加最少边的方案数. 很容 ...

  8. SGU 172.eXam(二分图染色)

    时间限制:0.25s 空间限制:4M 题意: 将n(n<200)个点分成两个集合,给出m(m<=30000)对不能在一个集合的点对,判断能否分成满足要求的集合,输出其中一个集合和集合的总数 ...

  9. noip 2010 关押罪犯 (二分图染色 并茶几)

    /* 二分图染色版本 两个监狱对应二部图的两部分 在给定的怨气值里二分 对于每一个Ci 进行染色判断是否合法 染色的时候 如果这条边的ci > Ci 这两个人就带分开 即染成不同的颜色 如果染色 ...

随机推荐

  1. 词向量模型word2vector详解

    目录 前言 1.背景知识 1.1.词向量 1.2.one-hot模型 1.3.word2vec模型 1.3.1.单个单词到单个单词的例子 1.3.2.单个单词到单个单词的推导 2.CBOW模型 3.s ...

  2. Os-Hax: 1 靶机记录

    靶机地址:172.16.1.197 Kali地址:172.16.1.108 1 信息搜集 靶机首页 相关信息查看 端口扫描: 开放22和80 目录扫描: 访问http://172.16.1.197/c ...

  3. SpringCloud(七)超时、重试

    一.Ribbon(单独配置) 可以通过ribbon.xx来进行全局配置.也可以通过服务名.ribbon.xx来对指定服务配置 全局配置: ribbon: ConnectTimeout: 3000 #连 ...

  4. tensorflow1.0 矩阵相乘

    import tensorflow as tf matrix1 = tf.constant([[3,3]]) matrix2 = tf.constant([[2],[2]]) product = tf ...

  5. vim的常用指令

    vim的常用指令如下: 光标运动: h,j , k, l (上/下/左/右) 删除字符: x 删除行 : dd 模式退出 : Esc,Insert(或者i) 退出编辑器 : q 强制退出不保存: q! ...

  6. awk和sed命令

    awk awk是一个强大的编辑工具,可以在无交互的情况下实现相当复杂的文本操作 awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 a ...

  7. ubuntu 下 使用GTK+、sqlite3、c语言的学生系统

    使用GTK+2.0.sqlite3数据库.c语言 的简易的学生管理系统 实现了基本的增删查改 效果图:

  8. 【集群实战】Rsync数据同步工具

    1. Rsync介绍 1.1 什么是Rsync? Rsync是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows ...

  9. [每日短篇] 1C - Spring Data JPA (0)

    2019独角兽企业重金招聘Python工程师标准>>> 准备把 Spring Data JPA 完整看一遍,顺便把关键要点记录一下.在写这篇文章的今天,再不用 Spring Boot ...

  10. Docker学习之搭建MySql容器服务

    描述 MySQL 5.6 SQL数据库服务器Docker镜像,此容器映像包含用于OpenShift的MySQL 5.6 SQL数据库服务器和一般用法.用户可以选择RHEL和基于CentOS的图像.然后 ...