链接:http://acm.timus.ru/problem.aspx?space=1&num=1106
描述:有n(n<=100)个人,每个人有一个或多个朋友(朋友关系是相互的)。将其分成两组,使每一组都有朋友在另一个组。
思路:大意就是求一个子图使其是二分图。直接用dfs染色。 实际上不是二分图,因为本题每个子集里边可以有边相连,只要满足题目给的条件就行了。比二分图简单了一些。
//g++ 4.7.2
#include <cstdio> #include <iostream> #include <cstring> #include <vector> using namespace std; const int M = 100 + 10; int color[M], vis[M]; //color[i]表示结点i的颜色,1表示黑色,2白色 vector<int> G[M]; void dfs(int u) { vis[u] = 1; for (int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if (!vis[v]) { color[v] = 3 - color[u]; dfs(v); } } } int main() { int n, t; scanf("%d", &n); for (int i = 1; i <= n; ++i) while (scanf("%d", &t) && t) { G[i].push_back(t); } memset(vis, 0, sizeof(vis)); memset(color, 0, sizeof(color)); for (int i = 1; i <= n; ++i) if (!vis[i]) { color[i]=1; //每个新连通分量起始点都要设置为1 dfs(i); } int sum = 0; for (int i = 1; i <= n; ++i) if (color[i] == 1) ++sum; printf("%d ", sum); for (int i = 1; i <= n; ++i) if (color[i] == 1) printf("%d ", i); return 0; }
还有一种方法差不多,看着像dfs实际不是,本题只需要对每个结点的邻接点染色就行,可以不用递归。
#include <cstdio> #include <iostream> #include <cstring> #include <vector> using namespace std; const int M = 100 + 10; int color[M], vis[M]; vector<int> G[M]; void coloring(int u) { vis[u] = 1; color[u] = 1; for (int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if (!vis[v]) color[v] = 3 - color[u]; vis[v] = 1; } } int main() { int n, t; scanf("%d", &n); for (int i = 1; i <= n; ++i) while (scanf("%d", &t) && t) { G[i].push_back(t); } memset(vis, 0, sizeof(vis)); memset(color, 0, sizeof(color)); for (int i = 1; i <= n; ++i) if (!vis[i]) coloring(i); int sum = 0; for (int i = 1; i <= n; ++i) if (color[i] == 1) ++sum; printf("%d ", sum); for (int i = 1; i <= n; ++i) if (color[i] == 1) printf("%d ", i); return 0; }