1. 程式人生 > 實用技巧 >三元環計數

三元環計數

三元環計數

參考部落格

洛谷模板

無向圖三元環計數

將無向圖轉化成有向圖,度大的指向度小的,若度一樣,按照編號排序。

列舉每個點x,將x的所有相鄰點標記,然後列舉x的相鄰點y,再列舉y的相鄰點z,
如果z已經被標記,那麼(x,y,z)就是如圖示的三元環。

複雜度 : \(O(n\sqrt n)\)

#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i = a;i <= b;i++)
#define repE(i,u) for(int i = head[u];i;i = E[i].next)

int n, m;

const int N = 1e5 + 10;
const int M = 2e5 + 10;

struct Edge {
	int to, next;
}E[M];
int head[N], tot;
void addEdge(int from, int to) {
	E[++tot] = Edge{ to,head[from] };
	head[from] = tot;
}
int deg[N], s[M], t[M];
int vis[N];

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++) {
		scanf("%d%d", s + i, t + i); deg[s[i]]++; deg[t[i]]++;
	}
	for (int i = 0; i < m; i++) {
		int u = s[i], v = t[i];
		if (deg[u] == deg[v] and u < v)swap(u, v);
		if (deg[u] < deg[v])swap(u, v);
		addEdge(u, v);
	}
	int ans = 0;
	rep(u, 1, n) {
		repE(i, u) vis[E[i].to] = u;
		repE(i, u) {
			int to = E[i].to;
			repE(j, to) {
				int v = E[j].to;
				if (vis[v] == u) {
					ans++;
				}
			}
		}
	}
	printf("%d\n", ans);
}