PAT甲級1139First Contact
阿新 • • 發佈:2020-09-01
題目連結
https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312
題解
題目要求
-
背景
男生A喜歡女孩B,A找男生C讓女孩D跟B說,其中C是A的朋友,D是B和C的朋友。女生也是這樣聯絡男生
-
輸入
- N:人的數量,1到300
- M:朋友關係的數量
- M個朋友關係:用4位數字表示一個人,其中負數代表性別是女生
- K:查詢數量,不超過100
- K次查詢:每次查詢是A和B的ID,假設A喜歡B
-
輸出
-
輸出有幾對C和D可以幫助A聯絡B
-
輸出這幾對C和D
-
如果A和B是異性,則A和C應該是同性,B和D同性;如果A和B是同性,則這4人性別應該相同
即A和C同性,B和D同性
-
先按C的ID非降序輸出,再按D的ID增序輸出
-
-
思路
- 使用鄰接矩陣表示兩個人是否是朋友,用鄰接表儲存一個人的同性朋友
- 給定A和B以後,列舉A的朋友C,列舉B的朋友D,如果C和D是朋友則儲存C和D
注意點
- 輸出時要以4位數字輸出,用
printf("%04d")
,第二和第三個測試點都測試了這個 - 如果用int接收一對朋友,-0000和0000對於int來說都是0,將無法得知這個人的性別
- 在這裡我對他們的id進行了處理:把女生對映到[0,9999],男生對映到[10000,19999]
- 也可以使用其他的雜湊方法
- 正常回路為A-C-D-B,不可以形成A-B-D-B或A-C-A-B的迴路,即AD不相等、BC不相等
- 寫迴圈程式碼時注意一些變數是否會隨著迴圈執行而改變,比如陣列大小、外層迴圈變數是否被內層迴圈改變
程式碼
// Problem: PAT Advanced 1139 // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312 // Tags: Graph Hash #include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; bool isFriend[20000][20000]; // 鄰接矩陣 vector<int> friends[20000]; // 鄰接表,同性朋友 struct Helper{ int c, d; }; int transform(string s){ // 將負數對映到[0,9999],將正數對映到[10000,19999] if (s[0] == '-') return abs(stoi(s)); else return 10000 + stoi(s); } int restore(int num){ // 將transform得到的[0,19999]的數字對映到[0,9999],即原來的[-9999,9999]取絕對值得到[0,9999],以進行輸出 if (num > 9999) return num - 10000; else return num; } bool helperCmp(Helper& h1, Helper& h2){ return h1.c == h2.c ? h1.d < h2.d : h1.c < h2.c; } int main() { int n, m, k, a, b, c ,d; string s, t; scanf("%d %d", &n, &m); for (int i = 0; i < m; i++){ // 將圖存入鄰接矩陣和鄰接表 cin >> s >> t; a = transform(s); b = transform(t); isFriend[a][b] = isFriend[b][a] = true; if ( (a<10000 && b<10000) || (a>9999 && b>9999) ){ // 同性則儲存到鄰接表 friends[a].push_back(b); friends[b].push_back(a); } } scanf("%d", &k); while (k--){ cin >> s >> t; a = transform(s); b = transform(t); vector<Helper> helpers; for (auto it1 = friends[a].begin(); it1 != friends[a].end(); it1++){ c = *it1; if (c == b) // C和B不能是一個人 continue; for (auto it2 = friends[b].begin(); it2 != friends[b].end(); it2++){ d = *it2; if (d == a) // D和A不能是一個人 continue; if (isFriend[c][d]) helpers.push_back({restore(c), restore(d)}); } } sort(helpers.begin(), helpers.end(), helperCmp); printf("%d\n", helpers.size()); for (auto it = helpers.begin(); it != helpers.end(); it++) printf("%04d %04d\n", it->c, it->d); } return 0; }
一份超時的程式碼
// Problem: PAT Advanced 1139
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312
// Tags: Graph Hash Map
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <unordered_map>
using namespace std;
struct Helper{
string c, d;
};
bool helperCmp(Helper& h1, Helper& h2){
return abs(stoi(h1.c)) == abs(stoi(h2.c)) ? abs(stoi(h1.d)) < abs(stoi(h2.d)) : abs(stoi(h1.c)) < abs(stoi(h2.c));
}
int main()
{
int n, m, k;
string a, b, c, d;
unordered_map<string, vector<string>> friends; // 會很耗時
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++){ // 儲存朋友關係
cin >> a >> b;
if (a[0] != '-')
a = '+' + a;
if (b[0] != '-')
b = '+' + b;
friends[a].push_back(b);
friends[b].push_back(a);
}
scanf("%d", &k);
while (k--){
cin >> a >> b; // a喜歡b
if (a[0] != '-')
a = '+' + a;
if (b[0] != '-')
b = '+' + b;
vector<Helper> helpers;
// 下邊這個大的for迴圈也很耗時間
for (auto it1 = friends[a].begin(); it1 != friends[a].end(); it1++){
c = *it1; // a的朋友c
if (b == c || a[0] != c[0]) // a和c不可以是同一個人,且應該是同性
continue;
for (auto it2 = friends[c].begin(); it2 != friends[c].end(); it2++){
d = *it2; // c的朋友d
if (a == d || b[0] != d[0]) // a和d不可以是同一個人,且應該是同性
continue;
if (find(friends[d].begin(), friends[d].end(), b) != friends[d].end()){
helpers.push_back({c, d});
}
}
}
sort(helpers.begin(), helpers.end(), helperCmp); // 按id升序儲存,達到題目輸出要求
int num = helpers.size();
printf("%d\n", num);
for (int i = 0; i < num; i++)
printf("%04d %04d\n", abs(stoi(helpers[i].c)), abs(stoi(helpers[i].d)));
}
return 0;
}
參考連結
https://blog.csdn.net/liuchuo/article/details/79065004
作者:@臭鹹魚
轉載請註明出處:https://www.cnblogs.com/chouxianyu/
歡迎討論和交流!