洛谷P1330 封锁阳光大学【dfs】

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

题意:一个无向边,一个河蟹可以占领一个点,但一个点只能被一个河蟹占领。

占领了一个点之后,这个点所有的边都删除。

问至少需要多少个河蟹可以让所有的边都被删除。

思路

乍一看有点无从下手。但实际上这个题就是一个将图上的点进行黑白着色的问题。

如果一个点被着了黑色,那么他的邻接点都要被着白色。

这道题给的图可能是一个森林,并且着色其实两个颜色可以对换。所以对于每一个连通块,至少应该有的河蟹数是两个颜色中较少的那个。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10 #include<queue>
11 #include<iostream>
12 
13 #define inf 0x7fffffff
14 using namespace std;
15 typedef long long LL;
16 typedef pair<int, int> pr;
17 
18 int n, m;
19 const int maxn = 10005;
20 const int maxm = 1e5 + 5;
21 int col[maxn]; 
22 int head[maxn], to[maxm * 2], nxt[maxm * 2];
23 int tot = 1;
24 
25 void add(int x, int y)
26 {
27     to[++tot] = y;
28     nxt[tot] = head[x];
29     head[x] = tot;
30     to[++tot] = x;
31     nxt[tot] = head[y];
32     head[y] = tot;
33 }
34 
35 int cnt[5];
36 bool dfs(int c, int x)
37 {
38     if(col[x] && col[x] != c){
39         return false;
40     }
41     else if(col[x])return true;
42     col[x] = c;
43     cnt[c]++;
44     for(int i = head[x]; i; i = nxt[i]){
45         int y = to[i];
46         if(!dfs(c ^ 1, y))return false;
47     }
48     return true;
49 }
50 
51 int main()
52 {
53     scanf("%d%d", &n, &m);
54     for(int i = 0; i < m; i++){
55         int x, y;
56         scanf("%d%d", &x, &y);
57         add(x, y);
58     }
59     bool flag = true;
60     int ans = 0;
61     for(int i = 1; i <= n; i++){
62         if(!col[i]){
63             if(!dfs(2, i)){
64                 flag = false;
65                 break;
66             }
67             else{
68                 ans += min(cnt[2], cnt[2^1]);
69                 memset(cnt, 0, sizeof(cnt));
70             }
71         }
72     }
73     if(!flag){
74         printf("Impossible
");
75     }
76     else{
77         printf("%d
", ans);
78     }
79 }
原文地址:https://www.cnblogs.com/wyboooo/p/11069558.html