zoukankan      html  css  js  c++  java
  • [csu1508 地图的四着色]二分图染色

    抽象后的题意:给一个不超过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=0;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?1:-1;
    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?1:-1;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 = 500;
    
    int n, m;
    
    struct Ufs {
        int fa[maxn];
        void init() { for (int i = 0; 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[30][30];
    int newnode[maxn];
    int c;
    
    ll ans = 0;
    
    bool E[30][30];
    int vis[30];
    
    bool dfs(int u, int c, int color) {
        vis[u] = color;
        for (int i = 0; i < c; i ++) {
            if (E[u][i]) {
                if (!vis[i]) if (!dfs(i, c, 3 - color)) return false;
                if (vis[i] == vis[u]) return false;
            }
        }
        return true;
    }
    
    int count(bool sube[30][30], int c) {
        int ans = 0;
        fillchar(vis, 0);
        for (int i = 0; i < c; i ++) {
            for (int j = 0; j < c; j ++) {
                E[i][j] = sube[i][j];
            }
        }
        for (int i = 0; i < c; i ++) {
            if (!vis[i]) {
                ans ++;
                if (!dfs(i, c, 1)) return - INF;
            }
        }
        return ans;
    }
    
    int useonecolor(bool sube[30][30], int c) {
        for (int i = 0; i < c; i ++) {
            for (int j = 0; j < c; j ++) {
                if (sube[i][j]) return 0;
            }
        }
        if (c) return 2;
        return 1;
    }
    
    int s[6], top = 0;
    
    void dfs(int p, int r) {
        if (r == 0) {
            int rst[5], extra[30];
            int t = 0;
            bool vis[30] = {}, sube[30][30] = {}, sube2[30][30] = {};
            for (int i = 0; i < top; i ++) {
                rst[i] = s[i];
                vis[s[i]] = true;
            }
            for (int i = 0; i < c; i ++) {
                if (!vis[i]) extra[t ++] = i;
            }
            for (int j = 0; j < top; j ++) {
                for (int k = 0; k < top; k ++) {
                    sube[j][k] = e[rst[j]][rst[k]];
                }
            }
            for (int j = 0; j < c - top; j ++) {
                for (int k = 0; k < c - top; k ++) {
                    sube2[j][k] = e[extra[j]][extra[k]];
                }
            }
            ll girl = count(sube, top), boy = count(sube2, c - top);
            if (girl < 0 || boy < 0) return ;
            girl = 1 << girl;
            boy = 1 << 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 + 1, r - 1);
            top --;
        }
    }
    
    char str[30][30];
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int cas = 0;
        while (cin >> n >> m) {
            ufs.init();
            for (int i = 0; i < n; i ++) {
                scanf("%s", str[i]);
                for (int j = 0; str[i][j]; j ++) {
                    if (j && str[i][j] == str[i][j - 1]) ufs.add(makeid(i, j), makeid(i, j - 1));
                    if (i && str[i][j] == str[i - 1][j]) ufs.add(makeid(i, j), makeid(i - 1, j));
                }
            }
            c = 0;
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < m; j ++) {
                    if (ufs.getfa(makeid(i, j)) == makeid(i, j)) newnode[makeid(i, j)] = c ++;
                }
            }
            fillchar(e, 0);
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < m; j ++) {
                    if (i && str[i][j] != str[i - 1][j]) e[newnode[ufs.getfa(makeid(i, j))]][newnode[ufs.getfa(makeid(i - 1, j))]] = true;
                    if (j && str[i][j] != str[i][j - 1]) e[newnode[ufs.getfa(makeid(i, j))]][newnode[ufs.getfa(makeid(i, j - 1))]] = true;
                }
            }
            for (int i = 0; i < c; i ++) {
                for (int j = 0; j < c; j ++) {
                    e[i][j] = e[i][j] || e[j][i];
                }
                //print(e[i], e[i] + c);
            }
            ans = 0;
            for (int i = 0; i <= min(5, c); i ++) dfs(0, i);
            printf("Case %d: ", ++ cas);
            cout << ans << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Java基础学习总结(41)——JPA常用注解
    Java基础学习总结(41)——JPA常用注解
    【云速建站】视频播放专题
    一招教你如何修复MySQL slave中继日志损坏问题
    【nodejs原理&源码赏析(3)】欣赏手术级的原型链加工艺术
    【云速建站】后台数据批量导入导出
    【云速建站】会员注册弹窗添加及设置
    【nodejs原理&源码赏析(2)】KOA中间件的基本运作原理
    【nodejs原理&源码赏析(1)】Express中间件系统的基本实现
    补习系列(5)-springboot- restful应用
  • 原文地址:https://www.cnblogs.com/jklongint/p/4751853.html
Copyright © 2011-2022 走看看