首先要给三角形的各个顶点标号,如右图所示。计算三角形的个数,首先要明确三角形的判定方法,怎么判断一个三角形是三角形。我们用边的相交来判定,在图中选择三条边,如果这三条边两两相交且交点就是某一条边的顶点,那么这三条边就构成了一个三角形。
要注意的是三条边两两相交还有两种不不能构成三角形的情形,一个是三条边相交于一点,一个是这三条边共线,即三个顶点在一条直线上。需要再判断完相交之后把这两种不符合实际的边剔除。
注意这里判断边和边相交,只判断是否相交于某一边的顶点而不是实际中的相互交叉,也就是说反映在程序中就是如果两条边共用一个顶点,则它们相交。而一条边只有两个顶点,因此相交的情形有四种。
判断三条边是否相交于一点很好判断,即是否3个交点相同。那判断三条边是否共线呢,这里采用的方法是,拿已知的三个顶点去在所有共线的顶点组合中去验证。上图中总共有7条边上顶点个数大于等于3,也就是说所有的共线情形就出现在这7条边中。对有可能构成三角形的三个顶点分别在7条边中逐一的验证直到点共线,或者7条边验证完。
代码如下:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int isInALine(char a,char b,char c)
{
vector<string> line={"adb","aejh","afki","agc","defg","bjkg","bhic"};
for(int i=0;i<line.size();i++)
{
if(line[i].find(a)!=string::npos&&line[i].find(b)!=string::npos&&line[i].find(c)!=string::npos)
{return 1;} //three pionts all on a line
}
return 0;
}
char getCrossPoint(const string& s1,const string& s2)
{
if(s1[0]==s2[0]) return s1[0];
if(s1[0]==s2[1]) return s1[0];
if(s1[1]==s2[0]) return s1[1];
if(s1[1]==s2[1]) return s1[1];
return '0';
}
int isTriangle(const string& str1,const string& str2,const string& str3)
{
char p1,p2,p3;
p1=getCrossPoint(str1,str2); // check if there exits a crosspoint between two line
if(p1=='0'){return 0;}
p2=getCrossPoint(str2,str3);
if(p2=='0'){return 0;}
p3=getCrossPoint(str1,str3);
if(p3=='0'){return 0;}
if(p1!=p2&&p2!=p3&&p1!=p3&&isInALine(p1,p2,p3)==0) //check if the three crosspoints is valid
{ return 1;}
return 0;
}
int main()
{
vector<string> graph={"ab","ad","db","ag","gc","ac","ah","ae","ej","jh",
"aj","eh","af","ak","ai","fk","fi","ki","de","df","dg","ef","eg",
"fg","bj","bk","bg","jk","jg","kg","bh","bi","bc","hi","hc","ic"};
int count=0;
int n=graph.size();
for(int i=0;i<n-2;i++)
for(int j=i+1;j<n-1;j++)
for(int k=j+1;k<n;k++){
if(isTriangle(graph[i],graph[j],graph[k])){
++count;
}
}
cout<<"The graph contains "<<count<<" triangle"<<endl;
}