k-truss

k-truss是一种子图结构,用于在图中寻找凝聚子图。类似的结构还有k-core

支持度(support):图的一条边e包含在k个三角形中,则support(e) = k

k-truss:图G的极大子图g。在g中,每条边的support >= k-2。
(也可以简化定义为support >= k)

很明显,对于两个正整数 k 1 > k 2 k_1\gt k_2 k1>k2 k 1 k_1 k1-truss ⊆ k 2 \subseteq k_2 k2–truss

truss decomposition:为了计算一个图中所有的k-truss,可以计算每条边的turssness。边e所在的最大k值的k-truss,trussness(e) = k。k-truss是所有trussness(e) >= k的边的诱导子图。

代码:

#include 
#include 
#include 
#include 
using namespace std;

vector<int> *g;
map<pair<int, int>, int> edge;
int n, m;  //最大顶点为n,边的数量为m
vector<int> sup, truss;   //边的支持度和truss
vector<pair<int, int>> edge2;

void BuildGraph(char* file);
void truss_decomposition();
int sup_calculation();
vector<int> k_truss(int K);

void BuildGraph(char* file)   //建立图
{
	FILE* f = fopen(file, "r");
	int a, b;
	//计算最大顶点编号为n
	while (fscanf(f, "%d %d", &a, &b) != EOF)
	{
		if (a > n) n = a;
		if (b > n) n = b;
		++m;
	}
	rewind(f);
	g = new vector<int>[n + 1];
	edge2.resize(m);
	m = 0;
	//int eid = 0;
	while (fscanf(f, "%d %d", &a, &b) != EOF)
	{
		if (a == b) continue;  //忽略指向自己的边
		if (a < b)  //令a>b
		{
			int t = a;
			a = b;
			b = t;
		}
		if (edge.find(pair<int, int>(a, b)) == edge.end())  //这条边目前不存在,避免重边
		{
			g[a].push_back(b);
			g[b].push_back(a);
			edge2[m] = pair<int, int>(a, b);
			edge[pair<int, int>(a, b)] = m;
			edge[pair<int, int>(b, a)] = m++;
		}
	}
	truss.resize(m);
	sup.resize(m);
	fclose(f);
}

void truss_decomposition()
{
	int maxsup = sup_calculation();
	vector<int> *bin = new vector<int>[maxsup + 1];
	for (int i = 0; i < m; ++i)
		bin[sup[i]].push_back(i);
	vector<bool> del(m, false);
	for (int i = 0; i <= maxsup; ++i)
	{
		for (int j = 0; j < bin[i].size(); ++j)
		{
			int eid = bin[i][j];
			if (del[eid] == true) continue;
			truss[eid] = i + 2;
			del[eid] = true;
			int x = edge2[eid].first;
			int y = edge2[eid].second;
			if (g[x].size() < g[y].size())
			{
				int t = x;
				x = y; 
				y = t;
			}
			for (int k = 0; k < g[y].size(); ++k)
			{
				int w = g[y][k];
				int e = edge[pair<int, int>(y, w)];
				if (del[e] == true) continue;
				if (edge.find(pair<int, int>(x, w)) != edge.end())  //xyw构成三角形
				{
					e = edge[pair<int, int>(x, w)];
					if (del[e] == true) continue;
					if (sup[e] > i)
					{
						sup[e]--;
						bin[sup[e]].push_back(e);
					}
					e = edge[pair<int, int>(y, w)];
					if (sup[e] > i)
					{
						sup[e]--;
						bin[sup[e]].push_back(e);
					}
				}
			}
		}
	}
	delete[] bin;
}


vector<int> k_truss(int K)   //计算指定k的k-truss
{
	queue<int> q;
	vector<int> res;
	vector<bool> del(m, false);
	int maxsup = sup_calculation();
	for (int i = 0; i < m; ++i)
	{
		if (sup[i] < K - 2)
			q.push(i);
	}
	while (q.empty() == false)
	{
		int eid = q.front();
		q.pop();
		if (del[eid] == true) continue;
		del[eid] = true;
		int x = edge2[eid].first;
		int y = edge2[eid].second;
		if (g[x].size() < g[y].size())
		{
			int t = x;
			x = y;
			y = t;
		}
		for (int k = 0; k < g[y].size(); ++k)
		{
			int w = g[y][k];
			int e = edge[pair<int, int>(y, w)];
			if (del[e] == true) continue;
			if (edge.find(pair<int, int>(x, w)) != edge.end())  //xyw构成三角形
			{
				e = edge[pair<int, int>(x, w)];
				if (del[e] == true) continue;
				sup[e]--;
				if (sup[e] < K - 2)
					q.push(e);
				e = edge[pair<int, int>(y, w)];
				sup[e]--;
				if (sup[e] < K - 2)
					q.push(e);
			}
		}
	}
	for (int i = 0; i < m; ++i)
		if (del[i] == false)
			res.push_back(i);
	return res;
}


int sup_calculation()
{
	int maxsup = 0;
	for (int i = 0; i <= n; ++i)
	{
		for (int j = 0; j < g[i].size(); ++j)
		{
			int w = g[i][j];    //i的相邻顶点
			if (i > w)
			{
				int eid = edge[pair<int, int>(i, w)];  //边(i,w)
				sup[eid] = 0;
				//degree(u)>degree(v)
				int u = g[i].size() > g[w].size() ? i : w;
				int v = g[i].size() > g[w].size() ? w : i;
				for (int k = 0; k < g[v].size(); ++k)   //w的相邻顶点
				{
					if (edge.find(pair<int, int>(u, g[v][k])) != edge.end())
						sup[eid]++;
				}
				if (sup[eid] > maxsup)
					maxsup = sup[eid];
			}
		}
	}
	return maxsup;
}

你可能感兴趣的:(k-truss)