洛谷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;
}

原文地址:https://www.cnblogs.com/handwer/p/13816561.html