PAT 1139 First Contact

题目链接:点击打开链接

思路:分析可知,有以下几个问题要处理,一是如何存储整个关系网;二是如何快速判断两个人之间是否存在朋友关系;三是如何将每个询问相应的结果存储并排序。题目没什么难度,采取合适的数据结构去处理以上三个问题即可,就是有一些坑点要注意。

七种方法(优化或不同方法):

一:前向星存图;利用set >快速判断朋友关系;set,cmp>存储结果

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct node{
  int v;
  int next;
}edge[200000];//开小了出现段错误 
int cnt,head[10000];
int sex[10000];
void Add(int u,int v){
  cnt++;
  edge[cnt].v = v;
  edge[cnt].next = head[u];
  head[u] = cnt;
  return;
}
void Nint(){
  cnt = 0;
  memset(head,0,sizeof(head));
  memset(sex,-1,sizeof(sex));
  return;
}
int Change(char s[]){
  int num = 0;
  if(s[0] == '-'){
    for(int i = 1;i <= 4;i++){
      num = num*10 + s[i] - '0';
    }
    sex[num] = 0;
    return num;
  }
  else{
    for(int i = 0;i < 4;i++){
      num = num*10 + s[i] - '0';
    }
    sex[num] = 1;
    return num;
  }
}
struct cmp{
  bool operator()(const pair &a,const pair &b)const{
    if(a.first != b.first){
      return a.first < b.first;
    }
    else{
      return a.second < b.second; 
    }
  }
};
set > s;
set,cmp> re;
int main(){
  int n,m,k;
  char a[10],b[10];
  scanf("%d%d",&n,&m);
  Nint();
  for(int i = 0;i < m;i++){
    scanf("%s%s",a,b);//这样读取的原因是有易错点:-0000 
    int aa = Change(a);
    int bb = Change(b);
    Add(aa,bb);
    Add(bb,aa);
    s.insert(pair(aa,bb));//使用make_pair会在PAT上编译错误 
    s.insert(pair(bb,aa));
  }
  scanf("%d",&k);
  while(k--){
    re.clear();
    scanf("%s%s",a,b);
    int aa = Change(a);
    int bb = Change(b);
    for(int i = head[aa];i;i = edge[i].next){
      int c = edge[i].v;
      if(bb == c || sex[aa] != sex[c]) continue;//易错点,别忘记判断找到的B不是D 
      for(int j = head[bb];j;j = edge[j].next){
        int d = edge[j].v;
        if(aa == d || sex[bb] != sex[d]) continue;//易错点,别忘记判断找到的C不是A
        if(s.find(pair(c,d)) != s.end()){
          re.insert(pair(c,d));
        }
      }
    }
    printf("%d\n",re.size());
    for(set,cmp>::iterator it = re.begin();it != re.end();it++){
      printf("%04d %04d\n",it->first,it->second);//%04d为易错点 
    }
  }
  return 0;
}
/*
  pair a(1,2);
  pair c;
  c = make_pair(2,3);//utility头文件中 
*/

二:vector存图;利用set >快速判断朋友关系;set,cmp>存储结果

优化:vector只存储和自己性别相同的朋友关系

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector v[10000];
int sex[10000];
int Change(char s[]){
	int num = 0;
	if(s[0] == '-'){
		for(int i = 1;i <= 4;i++){
			num = num*10 + s[i] - '0';
		}
		sex[num] = 0;
		return num;
	}
	else{
		for(int i = 0;i < 4;i++){
			num = num*10 + s[i] - '0';
		}
		sex[num] = 1;
		return num;
	}
}
struct cmp{
	bool operator()(const pair &a,const pair &b)const{
		if(a.first != b.first){
			return a.first < b.first;
		}
		else{
			return a.second < b.second; 
		}
	}
};
set > s;
set,cmp> re;
int main(){
	int n,m,k;
	char a[10],b[10];
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++){
		scanf("%s%s",a,b);//这样读取的原因是有易错点:-0000 
		int aa = Change(a);
		int bb = Change(b);
		if(sex[aa] == sex[bb]){//只存和自己性别相同的朋友 
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		s.insert(pair(aa,bb));//使用make_pair会在PAT上编译错误 
		s.insert(pair(bb,aa));
	}
	scanf("%d",&k);
	while(k--){
		re.clear();
		scanf("%s%s",a,b);
		int aa = Change(a);
		int bb = Change(b);
		for(int i = 0;i < v[aa].size();i++){
			int c = v[aa][i];
			if(bb == c || sex[aa] != sex[c]) continue;//易错点,别忘记判断找到的B不能是D 
			for(int j = 0;j < v[bb].size();j++){
				int d = v[bb][j];
				if(aa == d || sex[bb] != sex[d]) continue;//易错点,别忘记判断找到的C不能是A
				if(s.find(pair(c,d)) != s.end()){
					re.insert(pair(c,d));
				}
			}
		}
		printf("%d\n",re.size());
		for(set,cmp>::iterator it = re.begin();it != re.end();it++){
			printf("%04d %04d\n",it->first,it->second);//%04d为易错点 
		}
	}
	return 0;
}

三:vector存图;利用set >快速判断朋友关系;set,cmp>存储结果

优化:读取ID时,直接用string读取,利用string的length就可判断出性别是否一样,然后vector也只是存储性别相同的朋友关系。把string转化为无符号整数直接利用stoi(c++中)和abs(C语言中)函数即可。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector v[10000];
struct cmp{
	bool operator()(const pair &a,const pair &b)const{
		if(a.first != b.first){
			return a.first < b.first;
		}
		else{
			return a.second < b.second; 
		}
	}
};
set > s;
set,cmp> re;
int main(){
	int n,m,k;
	string a,b;
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++){
		cin >> a >> b;//这样读取的原因是有易错点:-0000
		int aa = abs(stoi(a));//stoi是C++的string中的函数;与atoi不同,atoi是C语言中的 
		int bb = abs(stoi(b));//abs也和fabs一样,是C语言math.h中的函数 
		if(a.length() == b.length()){
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		s.insert(pair(aa,bb));//使用make_pair会在PAT上编译错误
		s.insert(pair(bb,aa));
	}
	scanf("%d",&k);
	while(k--){
		re.clear();
		int aa,bb;
		scanf("%d%d",&aa,&bb);
		aa = abs(aa);
		bb = abs(bb);
		for(int i = 0;i < v[aa].size();i++){
			int c = v[aa][i];
			if(bb == c) continue;//易错点,别忘记判断找到的B不能是D 
			for(int j = 0;j < v[bb].size();j++){
				int d = v[bb][j];
				if(aa == d) continue;//易错点,别忘记判断找到的C不能是A
				if(s.find(pair(c,d)) != s.end()){
					re.insert(pair(c,d));
				}
			}
		}
		printf("%d\n",re.size());
		for(set,cmp>::iterator it = re.begin();it != re.end();it++){
			printf("%04d %04d\n",it->first,it->second);//%04d为易错点 
		}
	}
	return 0;
}

四:vector存图;利用set >快速判断朋友关系;vector存储结果

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector v[10000];
set > s;
struct node{
	int aa,bb;
	node(int c,int d):aa(c),bb(d){}
	bool operator<(const node &c)const{
		if(this->aa != c.aa){
			return this->aa < c.aa; 
		} 
		else{
			return this->bb < c.bb;
		}
	}
};
vector re;
int main(){
	int n,m,k;
	string a,b;
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++){
		cin >> a >> b;//这样读取的原因是有易错点:-0000
		int aa = abs(stoi(a));//stoi是C++的string中的函数;与atoi不同,atoi是C语言中的 
		int bb = abs(stoi(b));//abs也和fabs一样,是C语言math.h中的函数 
		if(a.length() == b.length()){
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		s.insert(pair(aa,bb));//使用make_pair会在PAT上编译错误
		s.insert(pair(bb,aa));
	}
	scanf("%d",&k);
	while(k--){
		re.clear();
		int aa,bb;
		scanf("%d%d",&aa,&bb);
		aa = abs(aa);
		bb = abs(bb);
		for(int i = 0;i < v[aa].size();i++){
			int c = v[aa][i];
			if(bb == c) continue;//易错点,别忘记判断找到的B不能是D 
			for(int j = 0;j < v[bb].size();j++){
				int d = v[bb][j];
				if(aa == d) continue;//易错点,别忘记判断找到的C不能是A
				if(s.find(pair(c,d)) != s.end()){
					re.push_back(node(c,d));
				}
			}
		}
		sort(re.begin(),re.end());
		printf("%d\n",re.size());
		for(int i = 0;i < re.size();i++){
			printf("%04d %04d\n",re[i].aa,re[i].bb);//%04d为易错点 
		}
	}
	return 0;
}

五:vector存图;利用set >快速判断朋友关系;vector >存储结果

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector v[10000];
bool cmp(pair a,pair b){
	if(a.first != b.first){
		return a.first < b.first;
	}
	else{
		return a.second < b.second; 
	}
}
set > s;
vector > re;
int main(){
	int n,m,k;
	string a,b;
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++){
		cin >> a >> b;//这样读取的原因是有易错点:-0000
		int aa = abs(stoi(a));//stoi是C++的string中的函数;与atoi不同,atoi是C语言中的 
		int bb = abs(stoi(b));//abs也和fabs一样,是C语言math.h中的函数 
		if(a.length() == b.length()){
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		s.insert(pair(aa,bb));//使用make_pair会在PAT上编译错误
		s.insert(pair(bb,aa));
	}
	scanf("%d",&k);
	while(k--){
		re.clear();
		int aa,bb;
		scanf("%d%d",&aa,&bb);
		aa = abs(aa);
		bb = abs(bb);
		for(int i = 0;i < v[aa].size();i++){
			int c = v[aa][i];
			if(bb == c) continue;//易错点,别忘记判断找到的B不能是D 
			for(int j = 0;j < v[bb].size();j++){
				int d = v[bb][j];
				if(aa == d) continue;//易错点,别忘记判断找到的C不能是A
				if(s.find(pair(c,d)) != s.end()){
					re.push_back(pair(c,d));
				}
			}
		}
		sort(re.begin(),re.end(),cmp);
		printf("%d\n",re.size());
		for(int i = 0;i < re.size();i++){
			printf("%04d %04d\n",re[i].first,re[i].second);//%04d为易错点 
		}
	}
	return 0;
}

六:vector存图;利用二维数组快速判断朋友关系;vector >存储结果

优化;直接利用二维数组标记朋友关系,方便。之前感觉就算开为bool,65536kB的内存还是不够bool[10^4][10^4],但试了一下可以,应该和系统内存分配有关,但要注意的一点是,当使用memset,会超出内存限制。即使这样,超过内存限制或者超过语言限制的过大数组最好不要使用!!!

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
vector v[10000];
bool map[10000][10000];
bool cmp(pair a,pair b){
	if(a.first != b.first){
		return a.first < b.first;
	}
	else{
		return a.second < b.second; 
	}
}
vector > re;
int main(){
	int n,m,k;
	string a,b;
	scanf("%d%d",&n,&m);
	//memset(map,false,sizeof(map));加了这个超出内存限制 
	for(int i = 0;i < m;i++){
		cin >> a >> b;//这样读取的原因是有易错点:-0000
		int aa = abs(stoi(a));//stoi是C++的string中的函数;与atoi不同,atoi是C语言中的 
		int bb = abs(stoi(b));//abs也和fabs一样,是C语言math.h中的函数 
		if(a.length() == b.length()){
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		map[aa][bb] = true;
		map[bb][aa] = true;
	}
	scanf("%d",&k);
	while(k--){
		re.clear();
		int aa,bb;
		scanf("%d%d",&aa,&bb);
		aa = abs(aa);
		bb = abs(bb);
		for(int i = 0;i < v[aa].size();i++){
			int c = v[aa][i];
			if(bb == c) continue;//易错点,别忘记判断找到的B不能是D 
			for(int j = 0;j < v[bb].size();j++){
				int d = v[bb][j];
				if(aa == d) continue;//易错点,别忘记判断找到的C不能是A
				if(map[c][d]){
					re.push_back(pair(c,d));
				}
			}
		}
		sort(re.begin(),re.end(),cmp);
		printf("%d\n",re.size());
		for(int i = 0;i < re.size();i++){
			printf("%04d %04d\n",re[i].first,re[i].second);//%04d为易错点 
		}
	}
	return 0;
}

七:vector存图;利用二维数组快速判断朋友关系;vector存储结果

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct node{
	int aa,bb;
	node(int a,int b):aa(a),bb(b){}
	bool operator<(const node &a)const{
		return aa != a.aa?aa < a.aa:bb < a.bb; 
	} 
};
bool map[10000][10000];
int main(){
	int n,m,k;
	string a,b;
	vector v[10000];
	//memset(map,false,sizeof(map));加了这个超出内存限制 
	scanf("%d%d",&n,&m);
	for(int i = 0;i < m;i++){
		cin >> a >> b;//这样读取的原因是有易错点:-0000
		int aa = abs(stoi(a));//stoi是C++的string中的函数;与atoi不同,atoi是C语言中的 
		int bb = abs(stoi(b));//abs也和fabs一样,是C语言math.h中的函数 
		if(a.length() == b.length()){
			v[aa].push_back(bb);
			v[bb].push_back(aa);
		}
		map[aa][bb] = true;
		map[bb][aa] = true;
	}
	scanf("%d",&k);
	while(k--){
		int aa,bb;
		vector re;
		scanf("%d%d",&aa,&bb);
		aa = abs(aa);
		bb = abs(bb);
		for(int i = 0;i < v[aa].size();i++){
			int cc = v[aa][i];
			if(bb == cc) continue;//易错点,别忘记判断找到的B不能是D
			for(int j = 0;j < v[bb].size();j++){
				int dd = v[bb][j];
				if(aa == dd) continue;//易错点,别忘记判断找到的C不能是A
				if(map[cc][dd]){
					re.push_back(node(cc,dd));//node{cc,dd}也可以,C++ 11新标准
				}
			}
		}
		sort(re.begin(),re.end());
		printf("%d\n",re.size());
		for(int i = 0;i < re.size();i++){
			printf("%04d %04d\n",re[i].aa,re[i].bb);//%04d为易错点 
		}
	}
	return 0;
}


你可能感兴趣的:(PAT 1139 First Contact)