ZCMU—1230

1230: Open Source

Time Limit: 1 Sec   Memory Limit: 128 MB
[ Submit][ Status][ Web Board]

Description

At an open-source fair held at a major university, leaders of open-source projects put sign-up sheets on the wall, with the project name at the top in capital letters for identification.

Students then signed up for projects using their userids. A userid is a string of lower-case letters and numbers starting with a letter.

The organizer then took all the sheets off the wall and typed in the information.

Your job is to summarize the number of students who have signed up for each project. Some students were overly enthusiastic and put their name down several times for the same project. That's okay, but they should only count once. Students were asked to commit to a single project, so any student who has signed up for more than one project should not count for any project.

There are at most 10,000 students at the university, and at most 100 projects were advertised.

Input Specification:

The input contains several test cases, each one ending with a line that starts with the digit 1. The last test case is followed by a line starting with the digit 0.

Each test case consists of one or more project sheets. A project sheet consists of a line containing the project name in capital letters, followed by the userids of students, one per line.

Output Specification:

For each test case, output a summary of each project sheet. The summary is one line with the name of the project followed by the number of students who signed up. These lines should be printed in decreasing order of number of signups. If two or more projects have the same number of signups, they should be listed in alphabetical order.

Input

Please Input Input Here

Output

Please Input Output Here

Sample Input

UBQTS TXT
tthumb
LIVESPACE BLOGJAM
philton
aeinstein
YOUBOOK
j97lee
sswxyzy
j97lee
aeinstein
SKINUX
1
0

Sample Output

YOUBOOK 2
LIVESPACE BLOGJAM 1
UBQTS TXT 1
SKINUX 0

【分析】

....map+set的混合应用...我居然1Y了我自己都不敢相信.....
题意就是有很多项目,项目的名字是大写的,每个项目后面跟着很多小写的是人名,每个人如果重复出现在这个项目下面只算1个人,一个人如果同时出现在两个或以上项目中,这个人就无效碰到1就表示一组数据输入结束,输出每个项目中的人数,并且项目按人数排序,如果人数一样那就按字典序从小到大。碰到0就结束程序;
首先需要一个map<string,int> name;来给人编号...让自己的思路更加清晰...
然后需要一个map<string,set<int>> f;来记录每个项目下的人,用set的原因是set有find()命令,并且平衡二叉树的结构使得find()速度非常快。
对每个人名,考虑他的是否出现在之前的项目中,如果他出现在之前的项目中,那么这个人就标记为无效,如果他只是单纯的重复出现在同一个项目中,那么直接insert()是没有问题的,因为set会去重。
为了计数方便,所以我加了一个map<int,string> work;来反向记录一个人所在的项目,因为我在标记无效的时候只是单纯的把这个人的编号标记为-1,在后面计数时还需要把这个无效的人从原来记录的那个项目中删除。所以判断name[work[]]是不是-1就可以了
然后就是在统计完人数后,对每个项目进行排序一个简单的cmp排序
【代码】
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
map<string,int> name;
map<string,set<int> > f;
map<int,string> work;
struct xx{
	string x;
	int y;
}a[10000];
int n,len;

int cmp(xx p,xx q)
{
	if (p.y==q.y) return p.x<q.x;
	return p.y>q.y;
}

void write()
{
	std::map<string, set<int> >::iterator it;
	int t=0;
	for (it=f.begin();it!=f.end();it++)
	{
	//	cout<<"****"<<it->first;
		int res=0;
		a[t].x=it->first;
		std::set<int>::iterator is;
		for (is=it->second.begin();is!=it->second.end();is++)
		{
		//	cout<<"***"<< *is;
			if (*is!=-1 && name[work[*is]]!=-1)
				res++;
		}
	//	cout<<endl;
		a[t].x=it->first;
		a[t].y=res;
		t++;
	}
	sort(a,a+t,cmp);
	for (int i=0;i<t;i++)
		cout<<a[i].x<<" "<<a[i].y<<endl;
}


int main()
{
	string s;
	string now;
	len=1;
	name.clear();
	f.clear();
	work.clear();
	while (getline(cin,s))
	{
		if (s=="0") break;
		if (s=="1")
		{
			write();
			len=1;
			name.clear();
			f.clear();
			work.clear();
		}
		else
		if (s[0]>='A' && s[0]<='Z')
		{
			now=s;
			f[now].insert(-1);
		}
		else
		if (name[s]!=-1)
		{
			int tt=0;
			if (!name[s]) name[s]=len,work[len]=s,len++;else tt=1;
			std::set<int>::iterator t=f[now].find(name[s]);
			if (t==f[now].end() && tt)
			{
				name[s]=-1;
				continue;	
			}
			f[now].insert(name[s]);
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值