hdu 4034 预处理+map映射字符串

原创 2016年08月29日 18:43:51

首先要注意输出时候有空格的问题,一行的最后一个空格不要输出!!切记!!

我的做法就是前n次,每得到一组关系,即A和B是朋友

就找到A的全部朋友,把B和他们的公共朋友数+1(A)

因为每组关系只出现一次,即对于人C来说,如果他现在不是A的朋友,那么B和C现在不会加

如果现在和A是朋友,那么现在会加一次,而以后不会出现A,C或者AB这个关系了,所以C,B有A这个公共朋友只会加这一次

如果现在C不是A的朋友,那么如果以后有CA,也会更新C和B的关系

这么一来公共朋友数就可以N*N的时间内完成

然后Q次访问每次只要O(N)就可以了(注意如果是朋友则不需要推荐)

然后就是一个排序的事


其实做题的时候我对上面的还没有太想清楚……

不过好巧居然过了

查了网上的方案,可以用字典树做映射,一个字典树的终止节点对应一个名字,在字典树的节点中用cnt编号,这样就可以有字符串logn找到他的编号

然后再设置一个保存字符串的数组,就可以由编号直接到字符串,我用两个map有点偷懒……讲道理一个就行了

#include<cstdio>
/*1.用map把人名字和序号对应 
  2.用gra[i][j]存储i和j的相同人个数
  3.进来一个relation a-b,把b到a和有关系的那些人,如果b和那些人没关系就+1 ,把a和b到有关系的那些人都+1
  真正做的时候如果发现a和b有关系,显然不用推荐。
  复杂度1000*1000log1000 * T 勉强可以吧 
*/ 
#include<algorithm>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 1500;
map<int,string> m1;
map<string,int> m2;
bool gra[maxn][maxn];
int com[maxn][maxn];
map<string,int> ::iterator itor; 
using namespace std;
set<string> s;
set<string> ::iterator itors;
int main()
{
    int T;	
    scanf("%d",&T);
    for(int test = 1; test <= T; test++){
    	int n,q;
		memset(gra,0,sizeof(gra));
    	memset(com,0,sizeof(com));
    	m1.clear();
    	m2.clear();
    	scanf("%d %d",&n,&q);
    	int cnt = 0;
		for(int i = 1; i <= n; i++){
    		string s1,s2;
    		cin >> s1 >> s2;
    		//cout << s1 << s2;
    		itor = m2.find(s1);
    		
    		if (itor == m2.end()){
    			m2[s1] = cnt;
    			
				m1[cnt] = s1;
			    cnt++;
			}
			
			itor = m2.find(s2);
			if (itor == m2.end()){
				m2[s2] = cnt;
				m1[cnt] = s2;
				cnt++;
			}
			int to = m2[s1];
			int from = m2[s2];
			gra[from][to] = 1;
			gra[to][from] = 1;
			for(int j = 0; j < cnt; j++)if (j != from){
				if (gra[j][to]){
					com[j][from]++;
					com[from][j]++;
				}
			}
			for(int j = 0; j < cnt; j++)if (j != to){
				if (gra[j][from]){
					com[j][to]++;
					com[to][j]++;
				}
			}
		}
		s.clear();
		printf("Case %d:\n",test);
		for(int i = 0; i < q; i++){
			//printf("q:\n");
			s.clear(); 
			string s1;
			cin >> s1;
			int ans = 0;
			int from = m2[s1];
			for(int j = 0; j < cnt; j++){
				if (j != from && !gra[from][j] && com[from][j] > ans){
					ans = com[from][j];
				}
			}
			//printf("ans:\n");
			if (ans == 0) printf("-\n");
			else{
			for(int j = 0; j < cnt; j++){
				if (j != from && !gra[from][j] && com[from][j] == ans){
					s.insert(m1[j]);
				}
			}
		    for(itors = s.begin(); itors != s.end(); itors++){
				if (itors != s.begin()) printf(" ");
				cout << *itors;
			}
			printf("\n");
			}
		}
	}
	return 0;
}

相关文章推荐

HDU 1430 魔板 (双向BFS)/(BFS预处理)+map判重

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1430 题意:给你两串字符串,有三种操作,让你从第一个变到第二个最小需要的变换步数。 题解:...

陈老师的多校联合20180808 map映射字符串

http://vjudge.net/contest/view.action?cid=51407#problem/A Description Your country has...

hdu1075(map映射)

What Are You Talking About Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/204800 K...

hdu 4034

题意:给你图中任意两点间的最短路距离,求原图中边数最少是多少? 这题应该不难想,显然如果可以由其他边迭代到这个点的话就不用连边,只要统计一下要删去的边数,而且很明确的一点是这里迭代只需要1个点去迭代...
  • xymscau
  • xymscau
  • 2011年09月16日 19:56
  • 913

hdu 4034 floyd Graph

题意:       给定有向图任意两点的最短距离。问,这样的图存在吗?存在的话输出这个图最少可以有的边长,不存在就impossible咯== 解:      比赛的时候看那么多人过,于是我们开始...

hdu 4034 Graph解题报告-Floyd思想

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4034 题目描述:给你一个n*n矩阵来表示一个图,矩阵的每个元素gij都表示i点到j点的最短路,其中对...

hdu 4034 Graph(深化最短路floyd)

题目大意:给出一个地图,已知每两个点之间的最短路径,求原图最少有多少条边。 特别注意: 1、这个图是有向图。 2、可以找到原图就是输出最少有多少条边,否则输出-1。 3、用floyd找到最短路以及进行...

hdu 4034 Graph(floyd)

Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Su...
  • WEYuLi
  • WEYuLi
  • 2013年07月29日 11:00
  • 502

HDU2112 - HDU Today - 最短路dijkstra+map映射

1.题目描述: HDU Today Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java...

Hash字符串常见用法总结 (HDU 1800 or map)

Hash字符串总结
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hdu 4034 预处理+map映射字符串
举报原因:
原因补充:

(最多只允许输入30个字)