题目: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 }