洛谷P1330 封锁阳光大学

Posted ylyvictor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1330 封锁阳光大学相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:https://www.luogu.org/problemnew/show/P1330

题目描述

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

阳光大学的校园是一张由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,任意两点之间最多有一条道路。

分析

这一题是一个好题。如果知道思路了,便会非常简单。但是如果不知道思路,却比较的难想出来。

我们来分析一下题目。首先,肯定要明确一点,那就是这个图是不一定联通的。于是,我们就可以将整张图切分成许多分开的连同子图来处理。然而最重要的事情是:如何处理一个连通图?

乍看下去,似乎无从下手,因为方案好像有很多种,根本就枚举不完。但是,关键要注意到题目中重要的两个条件,我们把它抽象成这两个要素:

①每一条边所连接的点中,至少要有一个被选中。②每一条边所连接的两个点,不能被同时选中。由此,可以推断出:

每一条边都有且仅有一个被它所连接的点被选中。

又因为我们要处理的是一个连通图。所以,对于这一个图的点的选法,可以考虑到相邻的点染成不同的颜色。

于是,对于一个连通图,要不就只有两种选法(因为可以全部选染成一种色的,也可以全部选染成另一种色的),要不就是impossible!

所以,我们只需要找到每一个子连通图,对它进行黑白染色,然后取两种染色中的最小值,然后最后汇总,就可以了。

另外,要判断impossible,只需要加一个used数组,记录已经遍历了哪些点。如果重复遍历一个点,且与上一次的颜色不同,则必然是impossible的。

参考代码:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <algorithm>
 6 using namespace std;
 7 inline int read(){
 8     char ch, c;
 9     int res;
10     while (ch = getchar(), ch < 0 || ch > 9) c = ch;
11     res = ch - 48;
12     while (ch = getchar(), ch >= 0 && ch <= 9)
13     res = (res << 3) + (res << 1) + ch - 48;
14     if (c == -) res = -res;
15     return res;
16 }
17 struct Edge{
18     int t;
19     int nexty;
20 }edge[200000];
21 int head[20000];
22 int cnt = 0;
23 void add(int a, int b){
24     cnt++;
25     edge[cnt].t = b;
26     edge[cnt].nexty = head[a];
27     head[a] = cnt;
28 }
29 bool used[20000] = {0};
30 int col[20000] = {0};
31 int sum[2];
32 bool dfs(int node, int color){
33     if (used[node]){
34         if (col[node] == color) return true;
35            else return false;
36     }
37     used[node] = true;
38     sum[col[node] = color]++;
39     bool tf = true;
40     for (int i = head[node]; i != 0 && tf; i = edge[i].nexty){
41         tf = tf && dfs(edge[i].t, 1 - color); 
42     }
43     return tf;
44 }
45 int main(){
46     int n, m;
47     scanf("%d%d", &n, &m);
48     int a, b;
49     while (m--){
50         scanf("%d%d", &a, &b);
51         add(a, b);
52         add(b, a);
53     }
54     int ans = 0;
55     for (int i = 1; i <= n; i++){
56         if (used[i]) continue;
57         sum[0] = sum[1] = 0;
58         if (!dfs(i, 0)){
59             printf("Impossible");
60             return 0;
61         }
62         ans += min(sum[0], sum[1]);
63     }
64     printf("%d", ans);
65     return 0;
66 }

 

以上是关于洛谷P1330 封锁阳光大学的主要内容,如果未能解决你的问题,请参考以下文章

洛谷——P1330 封锁阳光大学

洛谷 P1330 封锁阳光大学

洛谷 P1330 封锁阳光大学

洛谷P1330 封锁阳光大学

洛谷 P1330 封锁阳光大学 Label:染色问题

AC日记——封锁阳光大学 洛谷 P1330