题目链接: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. Codeforces 401D Roman and Numbers

    题目大意 Description 给定一个数 N(N<1018) , 求有多少个经过 N 重组的数是 M(M≤100) 的倍数. 注意: ①重组不能有前导零; ②重组的数相同, 则只能算一个数. ...

  2. MY JAVA-NOTE FIRST DAY

    今天是第一天开通博客,我很开心,总算拥有了自己的博客了,以后我会经常在博客里分享一些JAVA的心得.

  3. c#中开发ActiveX的学习笔记【转】

    http://www.cnblogs.com/yjmyzz/archive/2009/12/14/1623396.html 1.为什么要用ActiveX? 网页本身的功能是有限的,要想实现一些网页本身 ...

  4. Aws Dynamodb数据导出到S3

    本节将描写叙述怎样从一个或多个DynamoDB的表导出数据到S3的bucket中.在运行导出之前你须要提前创建好S3的bucket. 注意 假设你还没有使用过AWS Data Pipeline,在运行 ...

  5. 从头写一个Cucumber测试(一) Selenium Test

    转载:https://yaowenjie.github.io/%E7%BC%96%E7%A8%8B%E7%9B%B8%E5%85%B3/cucumber-test, 背景(废话不读系列)   前段时间 ...

  6. angular - 配置package.json -3

    package.json 包含了所有的开发包以及全局包以及其它项目信息,我们这个项目需要用到 bootstrap,所以我们添加信息. 添加包信息以后,我们用 npm install 安装,npm包管理 ...

  7. who命令

    who1.c #include <stdio.h>#include <utmp.h>#include <fcntl.h>#include <unistd.h& ...

  8. HDU 5667 :Sequence

    Sequence  Accepts: 59  Submissions: 650  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536 ...

  9. java对象访问

    下面这句代码: Object obj = new Object(); 对象引用在栈中,对象实体存在堆中,引用的方式有两种,分别是通过句柄访问对象和通过直接指针访问对象. Sun HotSpot使用第二 ...

  10. Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)(转)

    前面已经介绍了很多zuul的功能,本篇继续介绍它的另一大功能.在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选 ...