A1139 First Contact (30分)

博客提到暴力矩阵不合适,参考柳神的map用法,将矩阵换成用map存储边的权重,无权重时存储是否有关系的0/1,map第一个位置存转换后的一维索引,第二个位置存权重,还使用vector<int> edge[maxn]存储同性朋友。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发现暴力的矩阵不太合适,参考柳神的map用法,将矩阵换成使用map存储边的权重(如无权重,存储是否有关系0/1 即可),map<int,int >第一个位置存储转换后的索引(二维索引变一维),后一个位置存储权重

这里多了一个使用vector<int> edge[maxn] 来存储同性的朋友

#include<cstdio>
#include<string>
#include<iostream>
#include<vector>
#include <algorithm>//fill()在里面 
#include <cmath>
#include<queue>
#include<unordered_set>
#include<set> 
#include<map>
#include<unordered_map>
#include <cstdlib>//貌似是free,malloc等函数的头文件:含有NULL 
using namespace std;

//A1139 A(s:b)--C(b)--D(g)--B(g:e) :b男;g:女 
//给出关系图:
const int INF=1e9; //fill(map[0],map[0]+maxn*maxn,INF); 
const int maxn=10010;
//存储结构:学会新的存储结构的使用 :map和邻接表的配合使用://A1131也是一个思路 
unordered_map<int,bool> arr; 

//结构体是存储最后输出的一对朋友的,a是A的朋友,b是B的朋友 
struct node{
	int a,b;
};
//排序 
bool cmp(node x,node y){
	if(x.a==y.a)return x.b<y.b;
	return x.a<y.a; 
}
int main(){
	int n,m,k;
	scanf("%d %d",&n,&m);
	vector<int> v[10000];//邻接表v:只存同性朋友 
	for(int i=0;i<m;i++){
		string a,b;
		cin>>a>>b;
		if(a.length()==b.length()){
			//绝对值化:后面输出的id不需要正负号  无向图:存两次 
			v[abs(stoi(a))].push_back(abs(stoi(b)));
			v[abs(stoi(b))].push_back(abs(stoi(a)));
		}
		//在总的关系图中存储原始关系,如果没有权重,就直接存储代表是否有关系的数字 
		arr[abs(stoi(a))*10000+abs(stoi(b))]=arr[abs(stoi(b))*10000+abs(stoi(a))]=true;
		//map的存储?map用来存储映射关系:所以要将(a,b)变为一维的下标
		//由于是四位数所以*10000,将前一个的数字变为前四位数,后面的b是后四位数
		//如果是n位数,那么则*10^n 将其换到高n位数上
	}
	scanf("%d",&k);
	while(k--){
		int c,d;//查询还是用int:因为arr里面的映射第一个是int 
		cin>>c>>d;
		//其实就是A,B各找一个朋友就好了,不需要找路径:A--a,B--b 判断a和b是否认识 a--b
		//将找到的朋友对的结果存储在ans里
		vector<node> ans;
		//开始找!遍历的肯定是v:因为只有v里面的节点才是同性朋友:双层循环
		for(int i=0;i<v[abs(c)].size();i++){
			for(int j=0;j<v[abs(d)].size();j++){
				int f1=v[abs(c)][i];
				int f2=v[abs(d)][j];
				//根据题目要求,如果A,B同性且是朋友:得跳过再次寻找
				if(f1==abs(d)|| f2==abs(c))continue; 
				//判断两个朋友是否认识
				int pos=f1*10000+f2;
				//struct里面申明成员的时候int a,b;因此可以这样初始化一个对象 
				if(arr[pos]) ans.push_back(node{f1,f2}); 
			}
		}
		sort(ans.begin(),ans.end(),cmp);//输出排序
		printf("%d\n",ans.size());
        //注意输出格式 %04d 宽度为4,用0补齐
		for(int i=0;i<ans.size();i++){
			printf("%04d %04d\n",ans[i].a,ans[i].b);
		}	 
	}
			

	return 0; 
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值