P1330封锁阳光大学_bfs_黑白染色

更新一下, 这道题就是双色染色问题(原谅我这么叫他)


洛谷P1330封锁阳光大学

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

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

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

输入输出格式
输入格式:
第一行:两个整数N,M

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

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

input:
3 3
1 2
1 3
2 3
output:
Impossible


1.第一反应是这是一道图染色问题,因为相邻两个点有冲突,但分析发现不是(或者说不这么裸的是).
2.难道是模拟每一个结点开始进行遍历,看最后结果哪个更少是哪个? 不太可能,数据太大了.
3.想到一种方法:把一张图按照bfs分奇数层和偶数层,看哪个层点数最少,结果就是哪个. 如果同一层之间有点相连那么就Impossible. 发现可能是对的?
4.感觉像是从一张图中找出一棵生成树, 这棵树的层数是最小的.


综上所述:
相邻两个点之间一定有一个是有河蟹的,因为会有一条边. 那么就有两种状态: 染色或者不染色,那么用bfs分层,一层黑一层白,哪种层点少就选哪层,同一层邻边的Impossible. 一句话(我创的):黑白互斥层染色问题.

如何解决同一层的点之间有边的情况?

记录层次,发现从一个点扩展过来的点已经有层次了而且是和自己一个层,其实只有三种,上一层这一层下一层
上一层跳过,这一层Impossible(中途返回),下一层push,就ok了,回国头来统计黑白层点数量.
因为会比较层次,所以不像传统的遍历是建立visit数组,而是建立层数数组,以便互斥分析和结果统计.


结果只有40分. 似乎是这张图不一定是连通图, 所以要增加处理
这是个问题: 我有好多次都没有考虑图的联通性,以后一定要注意.
结果还是40分, 之前对的又有错了,之前错了又有对的.怎么会这样.
原因是重复判断了之前找过的点,加个vis数组去重.
然而现在是50分,该不会是思路出了问题吧.
妥协了,去看题解学习学习.
看题解发现思路差不多的,于是返回,找到了一个很明显的bug.原来是我之前移到多连通图时有几行代码要修改,但是我漏掉了一个地方, 所以出错了.

OK, 不完美地结束了. 经过思考对思维还是有一定地训练的.

最后贴代码

#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;

const int maxn = 10005;
int n, m;
vector<int> G[maxn]; // 邻接表存储. 
int layers[maxn] = {}; // 初始都是-1层 
bool vis[maxn] = {};

bool bfs(int i)
{
    queue<int> que;
    que.push(i);
    layers[i] = 1;
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        for (int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if (layers[v] == layers[u] - 1) continue; // 遍历到了上一层,分过层了continue 
            if (layers[v] == layers[u]) return false;  // 遍历到了同一层 
            layers[v] = layers[u] + 1;  // 下一层那就加上去. 
            que.push(v);
        }
    }
    return true;
}

int main()
{
    memset(layers, -1, sizeof(layers));
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (layers[i] == -1) {
            //cout << "i = " << i << endl;
            if (!bfs(i)) {
                cout << "Impossible";
                return 0;
            } else {
                int odd = 0, even = 0;
                for (int i = 1; i <= n; ++i) {
                    if (layers[i] + 1 && !vis[i]) {
                        vis[i] = true;
                        if (layers[i] & 1) odd++;
                        else even++;
                    }
                }
                //cout << min(even, odd) << endl; 
                ans += min(even, odd);
            }
        }
    }
    cout << ans;
}
/*
3 3
1 2
1 3
2 3

3 2
1 2
2 3

6 6
1 2
2 3
3 4
1 4
4 5
5 6
*/

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/81217540