PAT(Advanced level) 1139 First Contact(30)

题目要求:

  1. A和B:A对B心动,可同性可异性;A和C:同性别、朋友关系;B和D:同性别、朋友关系;C和D:朋友,可同性可异性。
  2. 给出所有人的关系图(可用二维数组或vector存储,用vector比较省内存),给出A和B,找出所有符合要求的C和D。
  3. 所有找出的C(i)和D(i)的输出顺序:优先输出小的C,若C相等则优先输出小的D。
  4. 每个人由一个4位数字表示(唯一),前面有’-‘表示女性。

解题思路:

1.本人选择用int存储每个人的id,但是输入时要用string,因为存在-0000的情况,若用int输入会将其存为0,搞反了性别,所以一开始先输入在string再转为int。负的id取正再加10000(如-1001存储为11001),详见代码。
2.使用二维数组vector fr[n+1] 存储关系网(无向图),由于id是4位数字比较难表示,所以直接输入时每新增一个人(如id为a)就用map存储其在fr中的位置(map[a]=i;fr[i]就表示a,可以存放a的所有朋友)。(这样会有点麻烦但是省内存。。。)
3.之后就是给你A和B,先遍历fr[map[A]]找出A的同性朋友C,如果A和B同性就要多考虑找到C不能是B,AB异性就不需要;每找到一个符合要求的C,再去找符合要求的D(同样D与B同性,如果AB同性还要考虑D不能是A也不能是C),最后判断D是不是C的朋友,是的话就是找到一对C和D。
4.由于答案要按一定顺序输出,所以用结点存C和D,设一个vector ans 来放这些结点,用sort对它们排序,比较简单易写。

细节/坑点

1.-0000情况
2.避免C是B、D是A或C的情况
3.哎呀好像都在上面说了…

AC代码(C++)

#include <bits/stdc++.h>
using namespace std;
#define w 10000
struct node{
	int c,d;
};
bool cmp(node a,node b)
{	return a.c!=b.c?a.c<b.c:a.d<b.d;	}
int main() {
	int n,m,k,a,b,c,d,x=1;
    string aa,bb;
    scanf("%d %d",&n,&m);
    vector<int> fr[n+1];
    map<int,int> mp;
    while(m--)
    {
    	cin>>aa>>bb;
    	a= aa[0]=='-'?w+abs(stoi(aa)):abs(stoi(aa));
    	b= bb[0]=='-'?w+abs(stoi(bb)):abs(stoi(bb));
    	if(mp[a]==0){	mp[a]=x++;	}
    	if(mp[b]==0){	mp[b]=x++;	}
    	fr[mp[a]].push_back(b);
    	fr[mp[b]].push_back(a);
	}
	scanf("%d",&k);
	while(k--)
	{
    	cin>>aa>>bb;
    	a= aa[0]=='-'?w+abs(stoi(aa)):abs(stoi(aa));
    	b= bb[0]=='-'?w+abs(stoi(bb)):abs(stoi(bb));
    	vector<node> ans;
    	int ax=mp[a],bx=mp[b];
    	bool ist=aa.size()==bb.size()?1:0;
    	for(int i=0;i<fr[ax].size();i++)
    	{
    		c=fr[ax][i];
			if(((a>=w&&c>=w)||(a<w&&c<w))&&((ist&&c!=b)||!ist))
    		{
                for(int j=0;j<fr[bx].size();j++)
    			{
    				d=fr[bx][j];
    				if(((b>=w&&d>=w)||(b<w&&d<w))&&((ist&&d!=a&&d!=c)||!ist))
    				{
    					int	cx=mp[c],l=0;
    					while(l<fr[cx].size()&&fr[cx][l]!=d)
    					{	l++;	}
    					if(l<fr[cx].size())
    					{
    						node t;
    						t.c= c>=w?c-w:c; t.d= d>=w?d-w:d; 
    						ans.push_back(t);
						}
					}
				}
			}
		}
    	sort(ans.begin(),ans.end(),cmp);
    	printf("%d\n",ans.size());
    	for(int i=0;i<ans.size();i++)
    	{	printf("%04d %04d\n",ans[i].c,ans[i].d);	}
	}
    return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值