codeforces B. Coach 解题报告
题目链接: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 解题报告的更多相关文章
- codeforces 31C Schedule 解题报告
题目链接:http://codeforces.com/problemset/problem/31/C 题目意思:给出 n 个 lessons 你,每个lesson 有对应的 起始和结束时间.问通过删除 ...
- codeforces 499B.Lecture 解题报告
题目链接:http://codeforces.com/problemset/problem/499/B 题目意思:给出两种语言下 m 个单词表(word1, word2)的一一对应,以及 profes ...
- codeforces 495C. Treasure 解题报告
题目链接:http://codeforces.com/problemset/problem/495/C 题目意思:给出一串只有三种字符( ')','(' 和 '#')组成的字符串,每个位置的这个字符 ...
- codeforces 490B.Queue 解题报告
题目链接:http://codeforces.com/problemset/problem/490/B 题目意思:给出每个人 i 站在他前面的人的编号 ai 和后面的人的编号 bi.注意,排在第一个位 ...
- CodeForces 166E -Tetrahedron解题报告
这是本人写的第一次博客,学了半年的基础C语言,初学算法,若有错误还请指正. 题目链接:http://codeforces.com/contest/166/problem/E E. Tetrahedro ...
- codeforces 489A.SwapSort 解题报告
题目链接:http://codeforces.com/problemset/problem/489/A 题目意思:给出一个 n 个无序的序列,问能通过两两交换,需要多少次使得整个序列最终呈现非递减形式 ...
- codeforces 485A.Factory 解题报告
题目链接:http://codeforces.com/problemset/problem/485/A 题目意思:给出 a 和 m,a 表示第一日的details,要求该日结束时要多生产 a mod ...
- codeforces 483A. Counterexample 解题报告
题目链接:http://codeforces.com/problemset/problem/483/A 题目意思:给出一个区间 [l, r],要从中找出a, b, c,需要满足 a, b 互质,b, ...
- codeforces 479C Exams 解题报告
题目链接:http://codeforces.com/problemset/problem/479/C 题目意思:简单来说,就是有个人需要通过 n 门考试,每场考试他可以选择ai, bi 这其中一个时 ...
随机推荐
- 洛谷1967货车运输 即 NOIP2013 DAY1 T3
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- 邁向IT專家成功之路的三十則鐵律 鐵律十九:IT人待業之道-寬心
說來很多人可能不相信,筆者從來不把失業當作是一件嚴重的事,相反的我會把它當作是一個很好的轉機.針對一個隨時做好準備的IT人,三個月或半年沒有上班完全沒有甚麼好擔心的.只是如何善用待業的時間,說實在的真 ...
- Linux如何显示文件指定行数的内容;显示第一行、中间几行和最后几行
1.tail -n +/-数字 文件名 2.head -n 数字 文件名 3.sed -n "开始行,结束行p" 文件名 4.sed -n '1p;20,40p; "显示 ...
- UNIX&Linux发展图谱
来自为知笔记(Wiz)
- C 标准库 - <limits.h>
C 标准库 - <limits.h> 简介 limits.h 头文件决定了各种变量类型的各种属性.定义在该头文件中的宏限制了各种变量类型(比如 char.int 和 long)的值. 这些 ...
- 百度地图之标注一组地理坐标<2>
一.需求 开发移动地图相关的应用有时会有这种需求:在地图上显示自己的定位,然后想查看周边使用这个应用的有哪些人.当然完毕这个功能须要后台数据的支持.你要把自己的位置信息发给后台,后台在依据你的位置查询 ...
- vs2012 MinGW 编译ffmeg 引用外部库libx264,librtmp
VS2012如何编译ffmpeg前面已经有文章讲过,本来主要讲述如何引用外部库libx264,librtmp, ffmpeg版本是3.0.2. 1. 下载x264源文件并编译 源码地址是http:// ...
- python 中的电子邮箱的操作
通过python 的代码实现对email的操作,包括发送邮件和读取邮件. import poplib import smtplib from email.header import decode_he ...
- Nginx详细的安装教程(linux)
转:https://blog.csdn.net/u013641234/article/details/73838472 Nginx作为一个web服务器,目前使用最多的就利用其负载均衡,本篇着重讲解的是 ...
- JavaScript读书笔记(1)
从今天开启每天看书记笔记模式,<JavaScript高级程序设计(第3版)> 1. Javascript最初是为了解决输入验证器的问题,现在已经发展成一门复杂的语言: 2. 语言标准为E ...