抽象后的题意:给一个不超过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. Python实现按键精灵(一)-键鼠操作

    需要安装 pywin32库 pip install pywin32 import win32api import time #鼠标移动 def mouse_move(x,y): win32api.Se ...

  2. vue2.x学习笔记(一)

    使用vue开发项目已经过了一段时间了,对其中的很多东西还是一知半解,于是想要系统学习一下.主要内容是参照官方中文网站https://cn.vuejs.org/v2/guide/,然后加上一些自己的理解 ...

  3. [PHP]$_SERVER参数详情

    来源:PHP中$_SERVER的详细参数与说明 $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名,与 document root相关.$_SERVER['argv'] #传递给该脚 ...

  4. 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD

    使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...

  5. 从零开始学习docker之docker的安装

    一.Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程 ...

  6. 一、Go语言由来与关键时间线

    Go语言,又称作Golang,是Google在2009年11月开源的开发语言.是一门静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言. Go是罗伯特·格瑞史莫(Robert Griesemer ...

  7. linux内核第一宏 container_of

    内核第一宏 list_entry()有着内核第一宏的美称,它被设计用来通过结构体成员的指针来返回结构体的指针.现在就让我们通过一步步的分析,来揭开它的神秘面纱,感受内核第一宏设计的精妙之处. 整理分析 ...

  8. Hadoop的下载和安装

    Hadoop的下载和安装 一:Hadoop的简介 Apache的Hadoop是一个开源的.可靠的.可扩展的系统架构,可利用分布式架构来存储海量数据,以及实现分布式的计算. Hadoop许使用简单的编程 ...

  9. Java工作流程引擎系统的退回规则 专题说明

    概述 说明:流程引擎的退回与发送,分别是前进与后退,它是流程引擎的基础功能操作,流程的退回根据不同的应用场景,也是需要不同的方式来控制,我们把这些方式叫做规则处理. 退回工作的场景相对复杂,由于与审核 ...

  10. thinkphp5 --接口实例

    这是我自己构思的案例,写的不好请多多指教. 后台接口的代码: public function index() { $res = array(); header("Access-Control ...