抽象后的题意:给一个不超过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. C++学习--编译优化

    常量折叠 把常量表达式的值求出来作为常量嵌在最终生成的代码中. 疑问:对于一个很复杂的常量表达式,编译器会算出结果再编译吗?亦或者是把这个表达式完全翻译成机器码,最终留给程序去解决? 分情况: 涉及的 ...

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

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

  3. 用 Python 获取百度搜索结果链接

    前言 近期有许多项目需要这个功能,由于Python实现起来比较简单就这么做了,代码贴下来觉得好点个赞吧~ 代码 # coding: utf-8 import os import time import ...

  4. centos7.4挂载硬盘

    场景:新网上买了台服务器,有个数据盘需要自己挂载 fdisk -l 能看见有一个85.9g的硬盘 然后mkfs -t ext4 /dev/sdb 格式化硬盘 mkdir /data新建data文件夹用 ...

  5. java 8 Streams简介

    目录 简介 Functional Interface Function:一个参数一个返回值 BiFunction:接收两个参数,一个返回值 Supplier:无参的Function Consumer: ...

  6. CTR学习笔记&代码实现4-深度ctr模型 NFM/AFM

    这一节我们总结FM另外两个远亲NFM,AFM.NFM和AFM都是针对Wide&Deep 中Deep部分的改造.上一章PNN用到了向量内积外积来提取特征交互信息,总共向量乘积就这几种,这不NFM ...

  7. 计算4的n次幂html代码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【DNS域名解析命令】host

    host - DNS lookup utility host命令是常用的分析域名查询工具,可以用来测试域名系统工作是否正常. 语法: host [-aCdlnrsTwv] [-c class] [-N ...

  9. 听说你在从事前端开发?那这10个JavaScript的优化问题你不得不知道!

    JavaScript的高效优化一直都是我们前端开发中非常重要的工作,也是很多开发人员无法做好的一部分内容,今天我总结了10个优化问题,大家可以参考来做优化,这其中很多问题都是大家经常遇到的哦. ==和 ...

  10. Vagrant (二) - 日常操作

    立即上手 上一节中,我们介绍了怎样安装 Vagrant,安装本身并不困难.本章节中我们首先要快速上手,以便获得一个直观的概念: 建立一个工作目录 打开命令行工具,终端工具,或者iTerm2等,建立一个 ...