题目意思:
有很多个项目(大写字母表示), 每个项目有很多学生报名,但是有效的报名是有规矩的。
如果有在多个项目下留名的,则此人无效;若一人在一项目下重复留名,只记一次。
题目最后要求输出,每个项目的项目名,以及有效的学生报名的人数。
本题要点:
1、这里,就是用map 暴力计算筛除 在多个项目报名的学生
2、最后输出结果,先按项目报名的学生人数从高到低,(如果相同)则按项目的字典序输出
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <string>
using namespace std;
const int MaxN = 110;
map<string, set<string> > g_map; // 项目名字对应于 所有的学生名字
map<string, int> g_stu; // 每个学生的报名 的 项目个数
struct Pro
{
string p;
int stu_num;
}projects[MaxN];
bool cmp(const Pro& a, const Pro& b)
{
if(a.stu_num != b.stu_num)
{
return a.stu_num > b.stu_num;
}
return a.p < b.p;
}
int main()
{
string line, project, stu;
while(getline(cin, line) && line != "0")
{
if(line == "1")
{
set<string>::iterator it = g_map[project].begin();
while(it != g_map[project].end())
{
g_stu[*it]++;
++it;
}
map<string, int>::iterator it2 = g_stu.begin();
while(it2 != g_stu.end())
{
if(it2->second == 1) //所有只报名一个项目的学生名次删除
{
g_stu.erase(it2++);
}else{
++it2;
}
}
map<string, set<string> >::iterator it3 = g_map.begin();
while(it3 != g_map.end())
{
set<string>::iterator it4 = it3->second.begin();
while(it4 != it3->second.end())
{
if(g_stu.find(*it4) != g_stu.end()) // 如果这个项目有的学生报名多个项目,则删除该学生的信息
{
it3->second.erase(it4++);
}else{
++it4;
}
}
++it3;
}
int cnt = 0;
it3 = g_map.begin();
while(it3 != g_map.end())
{
projects[cnt].p = it3->first;
projects[cnt++].stu_num = it3->second.size();
++it3;
}
sort(projects, projects + cnt, cmp);
for(int i = 0; i < cnt; ++i)
{
printf("%s %d\n", projects[i].p.c_str(), projects[i].stu_num);
}
g_map.clear();
g_stu.clear();
continue;
}
if(line[0] >= 'a' && line[0] <= 'z')
{
stu = line;
g_map[project].insert(stu);
}else{
if(g_map.size()> 0)//计算前一个项目组的信息
{
set<string>::iterator it = g_map[project].begin();
while(it != g_map[project].end())
{
g_stu[*it]++;
++it;
}
}
project = line;
}
}
return 0;
}
/*
UBQTS TXT
tthumb
LIVESPACE BLOGJAM
philton
aeinstein
YOUBOOK
j97lee
sswxyzy
j97lee
aeinstein
SKINUX
1
0
*/
/*
YOUBOOK 2
LIVESPACE BLOGJAM 1
UBQTS TXT 1
SKINUX 0
*/