无向图中三角形个数

来源:互联网 发布:51单片机at指令 编辑:程序博客网 时间:2024/06/06 02:07
给定一个无向图,求出此图中包含三角形的个数。    图中三角形指的是:在图中任意选择三个顶点,且这三个顶点之间任意两个点都有一条来自原图中的边。求出图中三角形个数有许多应用(1)在qq中两个好友之间的共同好友个数(2)好友推荐应用。(3)图的聚集系数。(4)小世界网络。本文中所给出的算法思想:    1.对图中的所有顶点按照度数由小到大进行排序。    2.计算图中每个顶点的A[v]集合。A[v]满足(1)集合中的元素是v的邻接点(2)排名在顶点v之后。此步骤可以保证每个三角形只被计算一次。    3.对图中每条边(u,v)进行遍历,每访问一条边(u,v),求出A[v]和A[u]的交集。累计每条边的交集个数。最后交集的个数即图中三角形的个数。如下图所示:    (1)顶点按照度数由小到大进行排序{2,0,4,3,1}。    (2)求出每个顶点的A[v]集合。A[0]={1,3}、A[1]={}、A[2]={1}、A[3]={1}以及A[4]={1,3}。    (3)求出每条边(u,v)中A[u]和A[v]的交集中元素的个数:(A[0],A[3])=1和(A[4],A[3])=1。
#include<iostream>#include<vector>#include<fstream>#include<algorithm>#include<time.h>using namespace std;void nodeIndegreeSort();//邻接点按照Id编号升序排序int intersect(vector<int> &v1, vector<int> &v2);//求v1和v2交集的个vector<vector<int>> mGraph;//图的存储结构vector<vector<int>> ve;//存储A[v]集合vector<int> degree;//图中节点的度int nodeNum;//图中节点的数目int edgeNum;//图中边的数目//读取图文件void readText(){ifstream fin;//fin.open("e:\\myData\\data13.txt");//读取文件//fin.open("e:\\myData\\citeseer.txt");//读取文件fin.open("e:\\myData\\cit-Patents.txt");//读取文件fin>>nodeNum>>edgeNum;mGraph.resize(nodeNum);degree.resize(nodeNum);ve.resize(nodeNum);int num1, num2, node;for(int i = 0; i < nodeNum; ++i){fin >> num1 >> num2;degree[i] += num2;for(int j = 0; j < num2; ++j){fin >> node;mGraph[i].push_back(node);mGraph[node].push_back(i);degree[node]++;}}fin.close();nodeIndegreeSort();for(int i = 0; i < nodeNum; ++i){ve[i].resize(degree[i]);}}void nodeIndegreeSort(){for(int i = 0; i < nodeNum; ++i){sort(mGraph[i].begin(),mGraph[i].end());}}//计算每个A[v]集合void rankByDegree(){for(int i = 0; i < nodeNum; ++i){int count = mGraph[i].size();int num = 0;for(int j = 0; j < count; j++){if(degree[i] < degree[mGraph[i][j]] || (degree[i] == degree[mGraph[i][j]] && i < mGraph[i][j])){ve[i][num++] = mGraph[i][j];}}ve[i].resize(num);}}//求交集int intersect(vector<int> &v1, vector<int> &v2){int num = 0;int count1 = v1.size();int count2 = v2.size();int i = 0;int j = 0;while(i < count1 && j < count2){if(v1[i] < v2[j]){i++;}else if(v1[i] > v2[j]){j++;}else{j++;i++;num++;}}return num;}//计算三角形个数int counting(){int sum = 0;for(int i = 0; i < nodeNum; ++i){int count = ve[i].size();for(int j = 0; j < count; ++j){sum += intersect(ve[i],ve[ve[i][j]]);}}return sum;}int main(void){readText();clock_t start,end;start = clock();rankByDegree();cout<<counting()<<endl;end = clock();cout<<"时间:"<<float(end - start)/CLOCKS_PER_SEC*1000<<endl;system("pause");return 0;}
数据集cit-Patents
三角形个数:7515023
时间:6272ms
算法分析:(1)我们没有对顶点按照度数由小到大进行排序,而是计算出每个顶点的度数。当求A[v]时,我们只需要比较这两个顶点度数大小以及他们之间的ID编号大小即可。(2)求交集时,A[v]集合中元素按照ID编号进行排序的,我们只需遍历一次两个集合就可以得到两个集合的交集。
0 0
原创粉丝点击