zoukankan      html  css  js  c++  java
  • 洛谷P1330《封锁阳光大学》

    原更新日期:2019-01-23 10:22:04

    对子连通图的染色

    题目描述

    曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。

    阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。

    询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。

    输入输出格式

    输入格式

    第一行:两个整数N,M

    接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。

    输出格式

    仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。

    输入输出样例

    输入样例#1

    3 3
    1 2
    1 3
    2 3
    

    输出样例#1

    Impossible
    

    输入样例#2

    3 2
    1 2
    2 3
    

    输出样例#2

    1
    

    说明

    【数据规模】

    1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。

    解题思路

    本题的图可能不为连通图(注意这个坑)

    阅读题目,我们得到了这样几条信息:
    「当某个点被封锁后,与这个点相连的道路就被封锁了」
    「当两只河蟹封锁了相邻的两个点时,他们会发生冲突」
    「封锁所有道路并且不发生冲突」

    总结一下就是:
    「要求每一条边有且仅有一个点被选择,求最少能选择多少点」

    然后我们就可以考虑用染色的方法做这一题

    我们枚举每一个点,以当前枚举到的起点为根对这个子连通图进行 DFS 染色(因为图可能不联通),答案累加每次染色的最小数量(黑色点数量和白色点数量中最小的)

    代码实现

    /* -- Basic Headers -- */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    
    /* -- STL Iterators -- */
    #include <vector>
    #include <string>
    #include <stack>
    #include <queue>
    
    /* -- External Headers -- */
    #include <map>
    #include <cmath>
    
    /* -- Defined Functions -- */
    #define For(a,x,y) for (int a = x; a <= y; ++a)
    #define Forw(a,x,y) for (int a = x; a < y; ++a)
    #define Bak(a,y,x) for (int a = y; a >= x; --a)
    #define head(a) Head[a].id
    #define nowcolor(a) Head[a].color
    #define visited(a) Head[a].used
    // 这样 define 有助于简化代码
    
    namespace FastIO {
        
        inline int getint() {
            int s = 0, x = 1;
            char ch = getchar();
            while (!isdigit(ch)) {
                if (ch == '-') x = -1;
                ch = getchar();
            }
            while (isdigit(ch)) {
                s = s * 10 + ch - '0';
                ch = getchar();
            }
            return s * x;
        }
        inline void __basic_putint(int x) {
            if (x < 0) {
                x = -x;
                putchar('-');
            }
            if (x >= 10) __basic_putint(x / 10);
            putchar(x % 10 + '0');
        }
        
        inline void putint(int x, char external) {
            __basic_putint(x);
            putchar(external);
        }
    }
    
    
    namespace Solution {
        int n, m, ans;
        int sum0, sum1;
        
        struct Graph {
            static const int MAXN = 10000 + 10;
            static const int MAXM = 100000 + 10;
            
            struct Node {
                int color, used, id;
                // 在一个数组中存储三个数量
                
                Node() { color = used = id = 0; }
            } Head[MAXN];
            
            struct Edge {
                int now, next;
            } edge[MAXM * 2];
            
            int cnt;
            
            inline void addEdge(int prev, int next, bool isR = true) {
                if (isR) { addEdge(next, prev, false); }
                edge[++cnt].now = next;
                edge[cnt].next = head(prev);
                head(prev) = cnt;
            }
            
            inline bool Color(int __id, int nowColor) {
                // 返回 true 为成功染色, false 反之
                if (visited(__id)) {
                    return nowcolor(__id) == nowColor;
                    // 如果当前被染过不同的颜色,就失败
                }
                visited(__id) = true;
                nowcolor(__id) = nowColor;
                if (nowColor) ++sum1;
                else ++sum0;
                bool __ans = true; 
                for (int e = head(__id); e && __ans; e = edge[e].next) {
                    int now = edge[e].now;
                    __ans = __ans & Color(now, nowColor ^ 1);
                    // 遍历与当前点相连的每一条边并 DFS
                }
                return __ans;
            }
        } g1;
        
        void __EXIT() {
            puts("Impossible");
            exit(0);
        }
    }
    
    signed main() {
    #define HANDWER_FILE
    #ifndef HANDWER_FILE
        freopen("testdata.in", "r", stdin);
        freopen("testdata.out", "w", stdout);
    #endif
        using namespace Solution;
        using FastIO::getint;
        n = getint();
        m = getint();
        For (i, 1, m) {
            int prev = getint();
            int next = getint();
            g1.addEdge(prev, next);
        }
        for (int i = 1; i <= n; ++i) {
            if (g1.visited(i)) continue;
            sum0 = sum1 = 0;
            if (!g1.Color(i, 0)) __EXIT();
            ans += std::min(sum0, sum1);
        }
        FastIO::putint(ans, '
    ');
        return 0;
    }
    
    
  • 相关阅读:
    webjars管理静态资源
    SpringCloud踩坑日记
    ELK日志搜索平台搭建
    新硬盘挂载到目录后目录原先数据消失解决办法
    nginx安装缺少依赖记录
    SpringCloud踩坑日记
    .bashrc配错刷新导致linux基础命令不能用修复
    nginx超时时间配置
    nginx日志切分shell脚本
    2019.10.10 实习日记
  • 原文地址:https://www.cnblogs.com/handwer/p/13816561.html
Copyright © 2011-2022 走看看