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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章