求大神帮忙看看这个程序,解释哈这个程序的算法。万分感谢!!
这是一个判断简单图是否为平面图的c++程序。希望大家能给出这个程序的算法细节,比如,找环、找面、找碎片、平面嵌入、找α-Path的算法,急用!!谢谢大家啊
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <algorithm>
#include <cassert>
#include <cctype>
using namespace std;
///图, 碎片, 环, 面以及道路的存储结构
typedef vector< list<int>* > graph;
typedef vector< list<int>* > fragment;
typedef list<int> circle; ///环用链表表示, 链表按顺时针记录环的点
typedef list<int> face; ///面用链表表示即可, 链表按顺时针记录面的点
typedef list<int> path;
const int MAXINT = ((unsigned)-1)>>1;
const int MAXPOINTCOUNT = 200;
int colour[MAXPOINTCOUNT]; ///为遍历设置的数组
const int WHITE = 0;
const int GRAY = 1;
const int BLACK = 2;
int parent[MAXPOINTCOUNT]; ///为遍历设置的数组
int depth[MAXPOINTCOUNT];
int pointKind[MAXPOINTCOUNT];
const int EMBEDED = -1;
const int AVAILABLE = 0;
bool pointEmbed[MAXPOINTCOUNT];
bool edgeEmbed[MAXPOINTCOUNT][MAXPOINTCOUNT];
int lowpoint[MAXPOINTCOUNT]; ///为找割点设置的数组
int lowneighbour[MAXPOINTCOUNT];
int pointType[MAXPOINTCOUNT];
const int NONCUTVERTEX = 0;
const int CUTVERTEX = 1;
int leave[MAXPOINTCOUNT];
int enter[MAXPOINTCOUNT];
int visitTime;
void removeBidegreePoint(graph *g) {}
void removeSingleDegreePoint(graph *g) {}
void removeParallelEdge(graph *g) {}
graph* createGraph(int pointCount)
{
graph* g = new graph;
for (int i=0; i<pointCount; i++) {
g->push_back(new list<int>);
}
return g;
}
graph* inputGraph(void)
{
int pointCount, edgeCount, from, to;
printf("请输入顶点个数:");
cin >> pointCount;
printf("\n请输入边的条数: ");
cin >> edgeCount;
graph *g = createGraph(pointCount);
cout<<"\n请输入图的信息:"<<endl;
for (int i=0; i<edgeCount; i++)
{
cin >> from >> to;
g->at(from)->push_back(to);
g->at(to)->push_back(from);
}
return g;
}
circle* getOneCircle(const graph *g, int start)
{
int pointCount = g->size();//图的节点数
for (int i=0; i<pointCount; i++)
{
colour[i] = WHITE;
}
queue<int> q;
q.push(start);
colour[start] = GRAY;
parent[start] = -1;
depth[start] = 0;
list<int>::iterator tra;
list<int>::iterator end;
int u,v;
///对图进行一次广度优先遍历即可以找到一个环
while (!q.empty())
{
u = q.front(); q.pop();
tra = g->at(u)->begin();
end = g->at(u)->end();
for (; tra != end; tra++)
{
v = *tra;//解引用操作
if (colour[v] == WHITE)
{
q.push(v);
colour[v] = GRAY;
parent[v] = u;
depth[v] = depth[u]+1;
}
///广度优先树的某一片树叶有在队列中的邻居, 则可以找到一个环
else if (colour[v] == GRAY)
{
goto buildTheCircle;
}
}
colour[u] = BLACK;
}
assert(!q.empty());
///从树叶结点u和邻居v回溯就可以找到一个环
buildTheCircle:
circle *c = new circle;
if (depth[v] > depth[u])
{
c->push_front(v);
v = parent[v];
}
while (u != v)
{
c->push_front(u);
c->push_back(v);
u = parent[u];
v = parent[v];
}
c->push_front(u);
return c;
}
vector< fragment* >* getFragments(const graph *g)
{
int pointCount = g->size();
for (int i=0; i<pointCount; i++)
{
colour[i] = WHITE;
if (pointEmbed[i] || g->at(i)->empty())
{
pointKind[i] = EMBEDED;
}
else
{
pointKind[i] = AVAILABLE;
}
}
vector< fragment* >* fragmentsVector = new vector< fragment* >;
int fragmentsCount = 0;
queue<int> q;
list<int>::iterator ltra;
list<int>::iterator lend;
///广度优先遍历找fragment,
///将fragment分成两类: 1包含末嵌入到平面的结点的, 2不包含...的
for (i=0; i<pointCount; i++)
{
if (colour[i] == WHITE)
{ ///fragment有可能不只一个
if (pointKind[i] == AVAILABLE)
{ ///从末嵌入平面的结点出发遍历
fragment *f = createGraph(pointCount);
fragmentsCount++;
colour[i] = GRAY;
parent[i] = -1;
pointKind[i] = fragmentsCount;
q.push(i);
while (!q.empty())
{
int u = q.front(); q.pop();
ltra = g->at(u)->begin();
lend = g->at(u)->end();
for (; ltra != lend; ltra++)
{
int v = *ltra;
if (colour[v] == WHITE)
{
if (pointKind[v] == AVAILABLE)
{
pointKind[v] = fragmentsCount;
parent[v] = u;
colour[v] = GRAY;
q.push(v);
f->at(u)->push_back(v);
f->at(v)->push_back(u);
}
///如果邻居结点已经嵌入平面,
///则只将边加入到fragment而不入队(中止从此类结点出发的遍历);
else if (pointKind[v] == EMBEDED)
{
f->at(u)->push_back(v);
f->at(v)->push_back(u);
}
}
///如果邻居结点在队列中或者结点已经嵌入平面,
///则只将边加入到fragment而不入队(中止从此类结点出发的遍历);
else if (colour[v] == GRAY || pointKind[v] == EMBEDED)
{
f->at(u)->push_back(v);
f->at(v)->push_back(u);
}
}
colour[u] = BLACK;
}
fragmentsVector->push_back(f);
}
///如果出发结点已经嵌入平面, 则只找那些仅包含已经嵌入平面的结点的fragment
///这些fragment只有一条边, edgeEmbed[]是用来提供已经嵌入平面的边的信息的
else if (pointKind[i] == EMBEDED)
{
ltra = g->at(i)->begin();
lend = g->at(i)->end();
for (; ltra!=lend; ltra++)
{
assert(i != *ltra);
if (pointKind[*ltra] == EMBEDED && !edgeEmbed[i][*ltra])
{
fragment *f = createGraph(pointCount);
f->at(i)->push_back(*ltra);
f->at(*ltra)->push_back(i);
fragmentsVector->push_back(f);
parent[*ltra] = i;
colour[*ltra] = BLACK;
}
}
colour[i] = BLACK;
}
}
}
return fragmentsVector;
}
vector< face* >* getFacesFromOneCircle(circle*& c)
{
vector< face* > *faces = new vector< face* >;
face* tempFace = new face; ///面用链表表示即可, 链表按顺时针记录面的点
tempFace->push_back(MAXINT); ///带MAXINT(当作无穷)的面是外面
circle::iterator ctra = c->begin();
circle::iterator cend = c->end();
for (; ctra != cend; ctra++)
{
tempFace->push_back(*ctra);
}
faces->push_back(tempFace);
faces->push_back(c);
c = NULL; ///circle c已经转变为其中一个face, 防止通过指针c改变它
return faces;
}
///标记已经嵌入到平面的点
void markEmbedPoint(const circle *c, int pointCount)
{
memset(pointEmbed, false, sizeof(bool)*pointCount);
circle::const_iterator ctra = c->begin();
circle::const_iterator cend = c->end();
for (; ctra != cend; ctra++)
{
if (*ctra != MAXINT)
{
pointEmbed[*ctra] = true;
}
}
}
///每次将alpha path嵌入到平面时, 更新已经嵌入到平面的结点
void addPoint(const path *alphaPath)
{
path::const_iterator ptra = alphaPath->begin();
path::const_iterator pend = alphaPath->end();
for (; ptra != pend; ptra++)
{
pointEmbed[*ptra] = true;
}
}
///标记已经嵌入到平面的边
void markEmbedEdge(const circle *c, int pointCount)
{
for (int i=0; i<pointCount; i++)
{
for (int j=0; j<pointCount; j++)
{
edgeEmbed[i][j] = false;
}
}
circle::const_iterator ctra = c->begin();
circle::const_iterator cend = c->end();
circle::const_iterator pre;
for (pre=ctra++; ctra != cend; ctra++)
{
edgeEmbed[*pre][*ctra] = true;
edgeEmbed[*ctra][*pre] = true;
pre = ctra;
}
edgeEmbed[*(c->begin())][*pre] = true;
edgeEmbed[*pre][*(c->begin())] = true;
}
///每次将alpha path嵌入到平面时更新已经嵌入到平面的边
void addEdge(const path *alphPath)
{
path::const_iterator ptra = alphPath->begin();
path::const_iterator pend = alphPath->end();
path::const_iterator pre;
for (pre = ptra++; ptra!=pend; ptra++)
{
edgeEmbed[*pre][*ptra] = true;
edgeEmbed[*ptra][*pre] = true;
pre = ptra;
}
}
///fragment与已经嵌入平面的子图的公共点就是contact point
bool* findContactPoint(const fragment *f)
{
int pointCount = f->size();
bool *contactPoint = new bool[pointCount];
memset(contactPoint, false, sizeof(bool) * pointCount);
for(int i=0; i < pointCount; i++)
{
if (pointEmbed[i] && !(f->at(i)->empty()))
{
contactPoint[i] = true;
}
}
return contactPoint;
}
///找一个face所包含的所有点
bool *findFacePoint(const face *fa, int pointCount)
{
bool *facePoint = new bool[pointCount];
memset(facePoint, false, pointCount * sizeof(bool));
face::const_iterator fatra = fa->begin();
face::const_iterator faend = fa->end();
for (; fatra != faend; fatra++)
{
if (*fatra != MAXINT) {
facePoint[*fatra] = true;
}
}
return facePoint;
}
bool isAdmissible(const fragment *fr, const face *fa)
{
int pointCount = fr->size();
bool *contactPoint = findContactPoint(fr);
bool *facePoint = findFacePoint(fa, pointCount);
bool admissible = true;
for (int i=0; i<pointCount; i++)
{
///face只有包含fragment的所有contact point, 它才是admissible face
if (contactPoint[i] && !facePoint[i])
{
admissible = false;
break;
}
}
delete[] contactPoint;
delete[] facePoint;
return admissible;
}
///如果存在fragment没有admissible face, 就返回false, 否则返回true
///引用型参数embedFaceIterator, embedFragmentIterator用来返回嵌入面和将要嵌入到面的碎片
bool getAdmissibleFace(const vector< fragment* > *fragments, const vector< face* > *faces,
vector< fragment* >::const_iterator &embedFragmentIterator,
vector< face* >::const_iterator &embedFaceIterator)
{
vector< fragment* >::const_iterator frtra = fragments->begin();
vector< fragment* >::const_iterator frend = fragments->end();
vector< face* >::const_iterator fctra = faces->begin();
vector< face* >::const_iterator fcend = faces->end();
bool foundEmbedPair = false;
for (; frtra != frend; frtra++)
{
int admissibleFaceCount = 0;
vector< face* >::const_iterator admissibleFaceIterator;
///对每一个fragment寻找其admissible face
fctra = faces->begin();
for (; fctra != fcend; fctra++)
{
bool temp = isAdmissible(*frtra, *fctra);
if (temp)
{
admissibleFaceCount++;
admissibleFaceIterator = fctra;
}
}
///有一个fragment没有admissible face, 这个图就不是平面图
if (admissibleFaceCount == 0)
{
//cout << "not planarity graph" << endl;
return false;
}