转自:https://blog.csdn.net/qq_34374664/article/details/57405987
题目:http://www.fjutacm.com/Problem.jsp?pid=2534
一,前引
做这道题的时候,傻乎乎的用链式前向星去存图,然后去遍历,最后因为太复杂了做不下去。( ˘•灬•˘ )
进而百度了一下这道题的解法,我对天,着实是秀这个解法,完全没想到。
二,思路
题意大概是就是求能构成 1->2->3->4 这种关系的羊的个数
① 注意有公羊和母羊之分,我们可以 +N, 错开储存。
② 每只公羊的朋友只有母羊,每只母羊的朋友只有公羊。
③ 其实我们既然储存了每只羊的朋友,我们可以只看第二点和第三点,第一点和第四点就包含在他们的朋友中了。
如图所示:
2 的朋友有 5 1 4 3
3 的朋友有 7 4 8 2
从图中可以清楚的看出来 其中有 四个点 的线 的个数是 3*3
第一个 3 是 母羊2 的朋友个数减一(为毛减一呢,因为要扣除 3 这个点)
第二个 3 是 公羊3 的朋友个数减一(为毛减一呢,因为要扣除 2 这个点)
④ 所以我们就可以遍历所有 母羊,累加 (当前的母羊的朋友个数-1)*(母羊的朋友公羊的朋友个数-1),反过来累加公羊也可以。
⑤ 最后乘以 2 就是答案了,因为朋友是双向的
三,代码
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<math.h> #include<bitset> #include<iostream> #include <string.h> #include<vector> using namespace std; vector<vector<int> >v(100000 * 2); int main(void) { int t; scanf("%d", &t); while (t--) { int n, m, k; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n + m; i++) v[i].clear(); for (int i = 1; i <= k; i++) { int x, y; scanf("%d%d", &x, &y); v[x].push_back(y + n); //公 -> 母 v[y + n].push_back(x); //母 -> 公 } long long sum = 0; for (int i = 1; i <= n; i++) { int men = v[i].size() ; // 第 i 只公羊的朋友个数 for (int j = 0; j < v[i].size(); j++) { int femen = v[v[i][j]].size(); // 第 i 只母羊的朋友个数 sum += (femen - 1)*(men-1); } } printf("%lld ", sum * 2); } system("pause"); return 0; }
end !!!
=========== ========== ======= ======= ====== ===== ==== === == =
过洞庭 唐珙 明
西风吹老洞庭波,一夜湘君白发多。
醉后不知天在水,满船清梦压星河。