Counting Stars HDU - 6184

http://acm.hdu.edu.cn/showproblem.php?pid=6184

先遍历所有的点,对于每个点再遍历所有的边,对于每一条边计算以这条边为三元环的某一条边的三元环个数,当然已经遍历过的点就不要再出现了

对于一条边,我们枚举时可以从这两个点任意取一个点去枚举第三个点,所以我们可以通过比较两个点谁的出边多来决定枚举谁,但实际就代码写法而言,是通过比较其出边与m的开平方的大小来决定的。

#include <iostream>
#include <cstring>
#include<cmath>
#include <queue> 
#include <cstdio>
#include <vector>
#include<set>

#pragma warning(disable:4996)
using namespace std;
typedef long long LL;
vector<int> G[100000 + 10];
bool vis[100000 + 10];
int link[100000 + 10], out[100000 + 10];
set<LL> S;
int main()
{
	int n, m;
	while (scanf("%d%d", &n, &m) == 2)
	{
		int u, v, B;
		LL ans , sum;
		S.clear();
		for (int i = 1; i <= n; i++) {
			G[i].clear();
			vis[i] = link[i] = out[i] = 0;
		}
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d", &u, &v);
			G[u].push_back(v);
			G[v].push_back(u);
			S.insert(LL(u*n + v));
			S.insert(LL(v*n + u));
			out[u]++;
			out[v]++;
		}
		B = sqrt(m + 0.5);
		ans = 0;
		for (int i = 1; i <= n; i++)
		{
			vis[i] = true;
			
			for (int j = 0; j < G[i].size(); j++)
				link[G[i][j]] = i;
			for (int j = 0; j < G[i].size(); j++)
			{
				sum = 0;
				int t = G[i][j];
				if (vis[t]) continue;
				if (out[t] <= B) {
				for (int k = 0; k < G[t].size(); k++)
					if (link[G[t][k]] == i) sum++;
				}
				else {
				for (int k = 0; k < G[i].size(); k++)
				    if (S.find(LL(G[i][k] * n + t)) != S.end()) sum++;
				}
				ans += sum * (sum - 1) / 2;
			}
			
		}
		printf("%lld\n", ans);
	}

	//system("pause");
}

猜你喜欢

转载自blog.csdn.net/qq_41776911/article/details/81411159