1139 First Contact (30分)/巧用图的存储方式

题目描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述

题目大意

A想对B表白,A会先找一个同性朋友C,C会找一个B的同性朋友D(D也是C的朋友),让D给B写信。给你一对A, B,要求找到所有的僚机C, D(成对)。按C的升序排列(如果C相同,按D升序排列)。

解析

  看似题目好像并不难,但是难点就是朋友关系以及每个人性别如何存储的问题。我的想法是用邻接矩阵存储,再开一个数组存储每个人的性别。类似于遍历的方法,一条路走到黑 >_<
  先找到C,再找到D。但是这样的话,由于邻接矩阵的大小为10000*10000,遍历找C,D的时候时间复杂度为O(n2),规模为10000,显然会超时。

  看了柳神的思路,太棒了~
  将每个人的同性朋友另外存到邻接表中,且思路是先找到A的同性朋友C和B的同性朋友D,再只需判断C、D是否是朋友即可(当然需要排除C为B或D为A的情况)。
  还有一个问题,就是怎么通过输入判断是否为同性?能根据a*b>0吗?答案是不能,因为题目中可能有ID为0000的情况,但是0000、-0000与其他ID的乘积都为0,无法区分。
  可以通过将ID作为字符串输入,再判断长度或者首字符。

AC代码

#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<unordered_set>
#include<unordered_map>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 10000;
int G[maxn][maxn];
vector<vector<int>> adj(maxn);
int main() {
#ifdef ONLINE_JUDGE
#else
	freopen("1.txt", "r", stdin);
#endif
	int n, m; scanf("%d %d", &n, &m);
	while (m--) {
		string a, b;
		cin >> a >> b;
		if (a.size() == b.size()) {
			int c1 = abs(stoi(a)), c2 = abs(stoi(b));
			adj[c1].push_back(c2);
			adj[c2].push_back(c1);
		}
		int c1 = abs(stoi(a)), c2 = abs(stoi(b));
		G[c1][c2] = G[c2][c1] = 1;
	}
	int k; scanf("%d", &k);
	while (k--) {
		int c1, c2;
		scanf("%d %d", &c1, &c2);
		c1 = abs(c1); c2 = abs(c2);
		vector<pair<int, int>> ans;
		for (int i = 0; i < adj[c1].size(); i++) {
			int v1 = adj[c1][i];
			if (v1 == c2) continue;
			for (int j = 0; j < adj[c2].size(); j++) {
				int v2 = adj[c2][j];
				if (v2 == c1) continue;
				if (G[v1][v2] == 1) ans.push_back({ v1,v2 });
			}
		}
		printf("%d\n", ans.size());
		sort(ans.begin(), ans.end());
		for (auto p : ans) {
			printf("%04d %04d\n", p.first, p.second);
		}
	}
	return 0;
}
发布了103 篇原创文章 · 获赞 9 · 访问量 4704

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104391158