题目链接:http://codeforces.com/problemset/problem/300/B

题目意思:给出n个students(n%3 = 0),编号依次为1~n,接下来有m行,每行有两个数:a和b(1<=a, b <= n),表示号码a的人想和号码b的人一起组队。但最终每一组的人最多只能为3个,至于组里只有2个或根本不成组的人可以通过组队变成3个人。问最后每组是否恰好为3人(包括原来不需要组队和组队后的情况),是则输出每组人的编号,否则输出-1。

一开始做的时候觉得像并查集,后来觉得做起来特别复杂,看了看tutorial,知道哪些情况为输出-1的:

情况1:组里面超过3人    情况2:2人组人数 > 1人组的人数(不成组)

根据这样硬用并查集来做,代码量非一般多!!!这就是不会算法的悲剧咯~~~

我的思路:

先用并查集来连边,保证大编号的指向最小编号的。

接着统计一人组,二人组,三人组的人数(分别为c1,c2,c3),以判断结果为-1的两种情况。

最后依次输出: 二人组 + 一人组,三人组,一人组 (除了三人组的情况其他两种都要组合)

(以后学好dfs一定要写条简短的代码,呜呜呜~~~整个晚上没了)

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std; const int maxn = + ;
int res[maxn], cnt[maxn], vis[maxn], vis1[maxn], vis2[maxn]; int find(int x)
{
while (x != res[x])
x = res[x];
return x;
} void merge(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx > fy)
res[fx] = fy;
else
res[fy] = fx;
} int main()
{
int n, m, i, j, k, a, b;
while (scanf("%d%d", &n, &m) != EOF)
{
for (i = ; i <= n; i++)
res[i] = i;
for (i = ; i < m; i++)
{
scanf("%d%d", &a, &b);
merge(a, b);
}
memset(vis, , sizeof(vis));
memset(vis1, , sizeof(vis1));
memset(cnt, , sizeof(cnt));
int flag, c2, c1, c3, f;
c1 = c2 = c3 = ;
for (i = ; i <= n; i++)
{
flag = ;
if (res[i] == i)
{
f = ;
for (j = i+; j <= n; j++)
{
if (res[j] == i)
{
cnt[i]++;
f = ; // 1 p num 的标记
}
}
if (cnt[i] == ) // 3 p num
c3++;
if (cnt[i] == ) // 2 p num
{
c2++;
vis1[i] = ;
}
if (cnt[i] >= ) // 组里的人多于3个
flag = ;
if (!f) // 1 p num
{
vis[i] = ;
c1++;
}
}
if (!flag)
break;
}
if (c2 > c1 || !flag)
printf("-1\n");
else
{
memset(vis2, , sizeof(vis2));
for (i = ; i <= n; i++) // 2 p num + 1 p num
{
if (res[i] == i && vis1[i]) // vis1[i] 保证是2 p num
{
printf("%d ", i);
vis2[i] = ; // sign used
for (j = i+; j <= n; j++)
{
if (!vis[j] && res[j] == i) // !vis[j]:保证先输出2 p num的人
{
vis2[j] = ;
printf("%d ", j);
for (k = ; k <= n; k++) // 1 p
{
if (res[k] == k && vis[k] && !vis2[k]) // vis[k]:1 p num 的人
{
printf("%d\n", k);
vis2[k] = ;
c1--; // 每输出一次减去一个1 p num的人
break;
}
}
}
}
}
}
for (i = ; i <= n; i++) // 3 p num
{
if (res[i] == i && !vis1[i] && !vis[i]) // !vis1[i]:保证不是2 p num;!vis[i]:保证不是1 p num
{
for (j = i; j <= n; j++)
{
if (res[j] == i && !vis[j])
{
printf("%d ", j);
vis2[j] = ;
}
}
printf("\n");
}
}
int count = ;
for (i = ; i <= n && c1; i++) // 剩下的 1 p num的人,每3个人合成1组
{
if (!vis2[i])
{
printf("%d ", i);
c1--;
count++;
if (count % == )
printf("\n");
}
}
}
}
return ;
}

codeforces B. Coach 解题报告的更多相关文章

  1. codeforces 31C Schedule 解题报告

    题目链接:http://codeforces.com/problemset/problem/31/C 题目意思:给出 n 个 lessons 你,每个lesson 有对应的 起始和结束时间.问通过删除 ...

  2. codeforces 499B.Lecture 解题报告

    题目链接:http://codeforces.com/problemset/problem/499/B 题目意思:给出两种语言下 m 个单词表(word1, word2)的一一对应,以及 profes ...

  3. codeforces 495C. Treasure 解题报告

    题目链接:http://codeforces.com/problemset/problem/495/C 题目意思:给出一串只有三种字符( ')','(' 和 '#')组成的字符串,每个位置的这个字符 ...

  4. codeforces 490B.Queue 解题报告

    题目链接:http://codeforces.com/problemset/problem/490/B 题目意思:给出每个人 i 站在他前面的人的编号 ai 和后面的人的编号 bi.注意,排在第一个位 ...

  5. CodeForces 166E -Tetrahedron解题报告

    这是本人写的第一次博客,学了半年的基础C语言,初学算法,若有错误还请指正. 题目链接:http://codeforces.com/contest/166/problem/E E. Tetrahedro ...

  6. codeforces 489A.SwapSort 解题报告

    题目链接:http://codeforces.com/problemset/problem/489/A 题目意思:给出一个 n 个无序的序列,问能通过两两交换,需要多少次使得整个序列最终呈现非递减形式 ...

  7. codeforces 485A.Factory 解题报告

    题目链接:http://codeforces.com/problemset/problem/485/A 题目意思:给出 a 和 m,a 表示第一日的details,要求该日结束时要多生产 a mod ...

  8. codeforces 483A. Counterexample 解题报告

    题目链接:http://codeforces.com/problemset/problem/483/A 题目意思:给出一个区间 [l, r],要从中找出a, b, c,需要满足 a, b 互质,b, ...

  9. codeforces 479C Exams 解题报告

    题目链接:http://codeforces.com/problemset/problem/479/C 题目意思:简单来说,就是有个人需要通过 n 门考试,每场考试他可以选择ai, bi 这其中一个时 ...

随机推荐

  1. JDK/Java SE官方文档汇总

    JDK一般是指Java SE. 1.5:https://docs.oracle.com/javase/1.5.0/docs/ 6:https://docs.oracle.com/javase/6/do ...

  2. 提高在Xcode上的工作效率

    对于在Xcode上提高工作效率,内功在这不提,对于外力,我将它分为三类: 工具.快捷键和小技巧.主要获得的路径是通过平时积累和看 WWDC12 上的 Session 402:Working Effic ...

  3. app 检查更新和更新

    第一种,手动检查 ////  Harpy.h//  Harpy////  Created by Arthur Ariel Sabintsev on 11/14/12.//  Copyright (c) ...

  4. iOS -- SKScene类

      SKScene类 继承自 SKEffectNode:SKNode:UIResponder:NSObject 符合 NSCoding(SKNode)NSCopying(SKNode)NSObject ...

  5. Qt中QVector与QList的应用

    首先來看看QVector 的基本使用方式,建立一個可容納兩個元素的QVector ,並使用索引方式存取元素值:QVector<double> vect(2); vect[0] = 1.0; ...

  6. 【Lintcode】二叉树的最大深度 - 比较简单,用递归比较好,不递归也能做,比较麻烦

    给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的距离. 您在真实的面试中是否遇到过这个题? Yes 样例 给出一棵如下的二叉树: 1 / \ 2 3 / \ 4 5 这个二叉树的 ...

  7. Nutch学习笔记二——抓取过程简析

    在上篇学习笔记中http://www.cnblogs.com/huligong1234/p/3464371.html 主要记录Nutch安装及简单运行的过程. 笔记中 通过配置抓取地址http://b ...

  8. 用Visual C++ 2010 载入动态链接库三部曲(使用第三方库的一般方法)

    以下以载入编译好的ACE动态链接库为例说明:这里如果你已经设置了环境变量ACE_ROOT ACE在VS2010下高速配置载入动态链接库三部曲:(这里如果你的ACE文件夹为E:\ACE_wrappers ...

  9. 【每日Scrum】第五天(4.15) TD学生助手Sprint1站立会议

    TD学生助手Sprint1站立会议(4.15) 任务看板 站立会议内容 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天和静姐,娇哥把图片3D画廊效果的功能实现了,GPS功能没什么进展,所以只能继 ...

  10. win7自带照片查看器

    win10如何找回自带的照片查看器   方法/步骤   1 首先,我们打开一个记事本,可以点击win+r打开运行框,然后在运行框中输入notepad.或者在桌面右键点击里面的新建,然后在新建中找到文本 ...