抽象后的题意:给一个不超过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. 再接再厉,JSONViewer现已支持Firefox、Microsoft Edge、360浏览器,可能是最好用的JSON格式化工具

    之前写的JSONViewer,截至目前在谷歌商店里已经有1000+的自然下载量了 为什么开发JSONViewer? 日常开发中,拿到接口输出的JSON一般会去在线的JSON格式化网站查看,但是在线格式 ...

  2. webform repeater 的使用

    1  repeater    定义: 重复器    根据数据库里的内容将repeater里的内容重复赋值 ,在itemtemplate下   配合<%# Eval(" ") ...

  3. 【Spring源码分析】预备篇

    前言 最新想学习一下Spring源码,开篇博客记录下学习过程,欢迎一块交流学习. 作为预备篇,主要演示搭建一个最简单的Spring项目样例,对Spring进行最基本梳理. 构建一个最简单的spring ...

  4. [半翻] 设计面向DDD的微服务

    这篇文章行文结构对照微软博客, 结合本人意译和多年实践的回顾思考形成此次读书笔记. Domian-driven Design 领域-驱动-设计(DDD)提倡基于(用例相关的现实业务)进行建模. 1. ...

  5. 让所有网站都提供API的Python库:Toapi

    这是一个让所有网站都提供API的Python库.以前,我们爬取数据,然后把数据存起来,再创造一个api服务以便其他人可以访问.为此,我们还要定期更新我们的数据.这个库让这一切变得容易起来.你要做的就是 ...

  6. radio样式

    .radio{ position: relative; border: 1px solid #999; border-radius: 50%; width: 12px; height: 12px; b ...

  7. 立体匹配-----NCC视差匹配

    目录 一.立体匹配算法 1.立体匹配算法分类 二.NCC 视差匹配方法 1.原理 2.NCC计算公式 3.算法流程 4.代码实现     5.不同场景运行 三.结论 四.遇到的问题及解决方法 一.立体 ...

  8. 理解java容器底层原理--手动实现HashSet

    HashSet的底层其实就是HashMap,换句话说HashSet就是简化版的HashMap. 直接上代码: package com.xzlf.collection2; import java.uti ...

  9. 元素均匀排列自动换行&二维数组前端遍历

    1.元素均匀排列并自动换行 display:flex; flex-wrap:wrap; 2.getFiled();取一行,取多行的话用getFiled(‘id’,true); 3.二维数组前端遍历: ...

  10. Test Test...

    标题: Test(一级标题) Test(二级标题) Test(三级标题) 列表: test(列表) Alpha Beta Gamma test 2 Delte Epsilon 链接: 点兔成金斐波那契 ...