傳送門:https://codeforces.com/problemset/problem/154/C
求出無向圖中,滿足所有出邊都相連或出邊直接連線點對的點對數。很顯然可以暴力列舉點對一對對去check,時間複雜度\(O(n^2+m)\)。
#include <bits/stdc++.h>
using namespace std;
inline int read() {
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true;
int res = c - '0';
while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0';
return flag ? -res : res;
}
const int N = 2e5 + 1;
int head[N], cnt, ans;
struct Edge {
int v, next;
} e[N];
void add(int u, int v) {
e[cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
map<pair<int, int>, int> mp;
bool check(int x, int y) {
for (int i = head[x]; ~i; i = e[i].next) {
int to = e[i].v;
if (to != y && !mp[make_pair(to, y)] && !mp[make_pair(y, to)]) return false;
}
for (int i = head[y]; ~i; i = e[i].next) {
int to = e[i].v;
if (to != x && !mp[make_pair(to, x)] && !mp[make_pair(x, to)]) return false;
}
return true;
}
int main() {
memset(head, -1, sizeof head);
int n = read(), m = read();
for (int i = 1; i <= m; ++i) {
int u = read(), v = read();
add(u, v);
add(v, u);
mp[make_pair(u, v)] = 1;
}
for (int i = 1; i <= n; ++i) for (int j = i + 1; j <= n; ++j) if (check(i, j)) ++ans;
printf("%d", ans);
return 0;
}
考慮最佳化,列舉點對肯定不可行,如何快速判定兩點出邊抵達的點相同?我們不妨把點集看作一個數,這樣就能透過排序快速計算點集相同的點對,這裡可以同行集合雜湊來實現,分有邊直連的點對和無邊直連的點對兩種情況計數即可。時間複雜度\(O(nlog_{2}n)\),瓶頸在於排序。
#include <bits/stdc++.h>
typedef unsigned long long ull;
using namespace std;
inline int read() {
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true;
int res = c - '0';
while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0';
return flag ? -res : res;
}
const int N = 1e6 + 1;
ull p[N], hs[N];
int u[N], v[N];
int main() {
int n = read(), m = read();
p[0] = 1;
for (int i = 1; i <= n; ++i) p[i] = p[i - 1] * 13;
for (int i = 1; i <= m; ++i) {
u[i] = read(), v[i] = read();
hs[u[i]] += p[v[i]];
hs[v[i]] += p[u[i]];
}
long long ans = 0;
for (int i = 1; i <= m; ++i) if (hs[u[i]] + p[u[i]] == hs[v[i]] + p[v[i]]) ++ans;
sort(hs + 1, hs + n + 1);
int cnt = 1;
for (int i = 2; i <= n; ++i) {
if (hs[i] == hs[i - 1]) ++cnt;
else {
ans += 1ll * cnt * (cnt - 1) / 2;
cnt = 1;
}
}
ans += 1ll * cnt * (cnt - 1) / 2;
printf("%lld", ans);
return 0;
}