基础稍微可以了,来练练手= =
题目意思:
给你N个小朋友,他们之间有M个关系,表示Ai小朋友不认识Aj小朋友
现在需要把他们划为两个集合,要求集合中小朋友不能互不认识
若不能则输出“Poor wyh”
若能,则需要第一个集合尽可能的多,并输出两个集合小朋友数量
思路:
首先是染色判定,这是必要的
然后贪心,当时这一步想了比较长时间
对于一个每一个新加入的节点,总会带来两个颜色集合点数量的增长
我们只需要每次把增长多的那个放进第一个集合就可以了
注意有个坑!当所有小朋友都认识的时候(即M为0)
不能将他们全都放在一个集合里得分出一个到集合2!
附上代码:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> #include <string> #include <math.h> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #pragma warning(disable:4996) #define Zero(a) memset(a, 0, sizeof(a)) #define Neg(a) memset(a, -1, sizeof(a)) #define All(a) a.begin(), a.end() #define PB push_back #define repf(i,a,b) for(i = a;i <= b; i++) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define root 1,n,1 #define ll long long #define MAXN 100005 #define mod 1000000007 using namespace std; vector <int> mp[MAXN]; int col[MAXN]; int n, m, num[3]; bool dfs(int u, int color){ col[u] = color; num[col[u]]++; for (int i = 0; i < mp[u].size(); ++i){ int v = mp[u][i]; if (col[v]){ if (col[v] != 3 - col[u]) return false; } else{ if (!dfs(v, 3 - color))return false; } } return true; } int main(){ int T; int u, v; while (~scanf("%d", &T)){ while (T--){ scanf("%d%d", &n, &m); for (int i = 0; i <= n; ++i){ mp[i].clear(); col[i] = 0; } for (int i = 0; i < m; ++i){ scanf("%d%d", &u, &v); mp[u].push_back(v); mp[v].push_back(u); } num[1] = num[2] = 0; int ans1 = 0, ans2 = 0; bool flag = true; for (int i = 1; i <= n; ++i){ if (!col[i]){ int pt1 = num[1], pt2 = num[2]; if (!dfs(i, 1)){ flag = false; break; } ans1 += max(num[1] - pt1, num[2] - pt2); ans2 += min(num[1] - pt1, num[2] - pt2); num[1] += pt1, num[2] += pt2; } } if (ans2 == 0) ans1--, ans2++; if (!flag || n <= 1) printf("Poor wyh\n"); else printf("%d %d\n", ans1, ans2); } } return 0; }
时间: 2024-10-13 00:08:18