// crikal.cpp : 定义控制台应用程序的入口点。
//
#include "iostream"
#include "vector"
#include "stack"
#include <fstream>
using namespace std;
#define MaxNumVertex 20 //最大顶点数
#define MaxNumEdge 40 //最大边数
#define infinity 65535//无穷大
typedef int elementtype; //elementtype 为int 型
//结点类型
struct ArcNode
{
elementtype data;//顶点信息
int weight ; //权重
ArcNode *nextarc ;//指向下一条弧
};
//表头
struct VNode
{
elementtype data;//顶点信息
ArcNode *firstarc;//指向第一条弧
};
typedef struct VNode AdjList[MaxNumVertex];
class graph{
public:
graph();
~graph();
elementtype insertvertex(elementtype v); //在图中增加一个顶点
elementtype insertedge(elementtype v,elementtype u,elementtype weight);//在图中增加一条从v顶点到u顶点的弧
elementtype firstadj(elementtype v);//求图g中顶点v的第一个邻接点
elementtype nextadj(elementtype v,elementtype m);//求图中顶点v的m邻接点之后的邻接点
elementtype firstpre(elementtype v);//求图中顶点v的第一个前驱
elementtype nextpre(elementtype v,elementtype m);//求图中顶点v的m前驱点之后的前驱点
elementtype degreein(elementtype v);//求图中顶点v的入度数
elementtype FindDegreein(elementtype ind[]);//各顶点的入度存放于入度数组中
elementtype degreeout(elementtype v);//求图中顶点v的入度数
elementtype FindDegreeout(elementtype oud[]);//各顶点的入度存放于入度数组中
elementtype EW(elementtype E[]);//最早发生时间的求解
bool CriticalPath();//关键路径
elementtype create();//创建图
int CurrentVertex;//当前顶点数
void show();
elementtype Getedge(elementtype v,elementtype u);//在图中获得v顶点到u顶点的权重
private:
AdjList vertices;
elementtype vertex[MaxNumVertex];//顶点表
elementtype edge[MaxNumVertex][MaxNumVertex];//图中弧的类型
};
/*
*初始化
*/
graph::graph()
{
CurrentVertex = 0;
}
/*
*在图中增加一个顶点
*/
elementtype graph::insertvertex(elementtype v)
{
//判断这个顶点是否已经存在
int i;
bool flags = true;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==v)
{
flags = false ;
break;
}
}
if(flags)
{
vertices[CurrentVertex].data = v ;
vertices[CurrentVertex].firstarc= NULL;
CurrentVertex++;
}else cout<<v<<"顶点已经存在!"<<endl;
return 0;
}
/*
*在图中增加一条从v顶点到u顶点的弧
*/
elementtype graph::insertedge(elementtype v,elementtype u,elementtype weight)
{
int i ;
ArcNode *s = new ArcNode;
s->data = u;
s->weight = weight;
for( i = 0 ; i < CurrentVertex ; i ++ )
{
if(vertices[i].data==v)//找到顶点v对应的表头
{
ArcNode *p = new ArcNode;
ArcNode *q = new ArcNode;
p = vertices[i].firstarc ;
bool flags = true;
if(p==NULL)
{
//cout<<"Yes\n";
s->nextarc = p;
vertices[i].firstarc = s ;
// cout<<vertices[i].data<<","<<vertices[i].firstarc->data<<","<<vertices[i].firstarc->weight<<endl;
}else
{
while(p!=NULL)
{
if(p->data!=u)
{
q = p;
p = p->nextarc;
}else{
flags = false;
break;
}
}
if(flags)
{
s->nextarc = q->nextarc;
q->nextarc = s;
}else cout<<v<<"->"<<u<<"这条弧弧已经存在!"<<endl;
}
}
}
return 0;
}
/*
*求图中顶点v的第一个邻接点
*/
elementtype graph::firstadj(elementtype v)
{
int i;
elementtype u = 0;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==v)//找到顶点v对应的表头
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
if(p)
{
u = p->data;
}else
{
break;
}
}
}
return u;
}
/*
*求图中顶点v的m邻接点以后的邻接点
*/
elementtype graph::nextadj(elementtype v,elementtype m)
{
int i;
elementtype u = 0;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==v)//找到顶点v对应的表头
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
while(p)
{
if(p->data!=m)
{
p = p ->nextarc ;
}else break;
}
if(p&&p->data==m&&p->nextarc) u = p->nextarc->data ;
break;
}
}
return u;
}
/*
*求图中顶点v的第一个前驱
*/
elementtype graph::firstpre(elementtype v)
{
int i;
elementtype u = 0;
bool flags = false;
for(i=0;i<CurrentVertex;i++)
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
while(p)
{
//cout<<p->data;
if(p->data==v)
{
u = vertices[i].data;
flags = true;
break;
}
p = p ->nextarc;
}
if(flags)break;
}
return u;
}
/*
*求图中顶点v的m前驱点之后的前驱点
*/
elementtype graph::nextpre(elementtype v,elementtype m)
{
int i,j;
elementtype u = 0;
bool flags = false;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==m)
{
ArcNode *p = new ArcNode;
for(j=i+1;j<CurrentVertex;j++)
{
p = vertices[j].firstarc ;
while(p)
{
if(p->data==v)
{
u = vertices[j].data;
flags = true;
break;
}
p = p ->nextarc;
}
if(flags)break;
}
break;
}
}
return u;
}
/*
*求图中顶点v的入度数
*/
elementtype graph::degreein(elementtype v)
{
int i,num = 0;
for(i=0;i<CurrentVertex;i++)
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
while(p)
{
if(p->data==v)
{
num++;
break;
}
p = p ->nextarc;
}
}
return num;
}
/*
*每个顶点的入度
*/
elementtype graph::FindDegreein(elementtype ind[])
{
int i;
for(i=0;i<CurrentVertex;i++)
{
ind[vertices[i].data] = degreein(vertices[i].data);
}
return 0;
}
/*
*求图中顶点v的出度数
*/
elementtype graph::degreeout(elementtype v)
{
int i,num = 0;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==v)
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
while(p)
{
num++;
p = p ->nextarc;
}
break;
}
}
return num;
}
/*
*每个顶点的出度
*/
elementtype graph::FindDegreeout(elementtype outd[])
{
int i;
for(i=0;i<CurrentVertex;i++)
{
outd[vertices[i].data] = degreeout(vertices[i].data);
}
return 0;
}
/*
*在图中获得v顶点到u顶点的权重
*/
elementtype graph::Getedge(elementtype v,elementtype u)
{
int i;
int weight = 0;
for(i=0;i<CurrentVertex;i++)
{
if(vertices[i].data==v)
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
while(p)
{
if(p->data==u)
{
weight =p->weight;
break;
}
p = p ->nextarc;
}
break;
}
}
return weight;
}
void graph::show()
{
int i;
elementtype m;
cout<<"test"<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )
{
ArcNode *p = new ArcNode;
p = vertices[i].firstarc ;
cout<<"表头:"<<vertices[i].data<<endl;
while(p!=NULL)
{
cout<<p->data<<","<<p->weight<<endl;
p = p->nextarc;
}
}
cout<<"第一个邻接点:"<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<vertices[i].data<<","<<firstadj(vertices[i].data)<<endl;
cout<<endl;
cout<<"第2个邻接点:"<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )
{
cout<<vertices[i].data<<":";
m = firstadj(vertices[i].data) ;
while(m)
{
m = nextadj(vertices[i].data,m);
cout<<m<<",";
}
cout<<endl;
}
cout<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"第一个前驱点:"<<vertices[i].data<<","<<firstpre(vertices[i].data)<<endl;
//cout<<"第一个前驱点:"<<vertices[CurrentVertex-1].data<<endl;
//cout<<firstpre(vertices[CurrentVertex-1].data)<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )
{
cout<<"第2个前驱:"<<vertices[i].data<<":";
m = firstpre(vertices[i].data) ;
while(m)
{
m = nextpre(vertices[i].data,m);
cout<<m<<",";
}
cout<<endl;
}
cout<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"入度数目:"<<vertices[i].data<<","<<degreein(vertices[i].data)<<endl;
elementtype ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
FindDegreein(ind);//
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"入度数目:"<<ind[vertices[i].data]<<endl;
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"出度数目:"<<vertices[i].data<<","<<degreeout(vertices[i].data)<<endl;
elementtype outd[MaxNumVertex];//求各顶点的出度存放于出度数组outd中
FindDegreeout(outd);//求各个结点的出度
for( i = 0 ; i < CurrentVertex ; i ++ )cout<<"出度数目:"<<vertices[i].data<<","<<outd[vertices[i].data]<<endl;
cout<<Getedge(vertices[CurrentVertex-2].data,vertices[CurrentVertex-1].data)<<endl;
}
/*
*最早发生时间的求解
*/
elementtype graph::EW(elementtype E[])
{
int i;
stack<elementtype> s;//定义并初始索要用到的栈
elementtype x,w,ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
FindDegreein(ind);
for(i=0;i<CurrentVertex;i++)//各个结点最早发生时间的初始化
{
E[vertices[i].data] = -1;
}
for(i=0;i<CurrentVertex;i++)//将入度为0的顶点入栈
{
if(degreein(vertices[i].data)==0)
{
s.push(vertices[i].data);
E[vertices[i].data] = 0;//第一个入度为0的结点的最早发生时间为0
}
}
int count =0;//用于统计已经完成的结点数目
while(!s.empty())
{
x = s.top();
count++;//计数
s.pop();
w = firstadj(x);//开始对v的各个后继顶点的入度-1
while(w!=0)
{
if(E[w]<(E[x]+Getedge(x,w)))
{
E[w] = E[x]+Getedge(x,w);//更新w的最早发生时间
}
if(!(--ind[w]))//若w的入度-1后为0,则入栈
{
s.push(w);
}
w = nextadj(x,w);
}
}
for(i=0;i<CurrentVertex;i++)//各个结点最早发生时间的初始化
{
cout<<E[vertices[i].data]<<endl;
}
if(count<CurrentVertex)return false;//产生有回路的标志
else return true;
return 0;
}
/*
*关键路径
*/
bool graph::CriticalPath()
{
int i;
stack<int> s;//定义并初始索要用到的栈
elementtype x,w,ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
elementtype outd[MaxNumVertex];//求各顶点的出度存放于出度数组outd中
elementtype E[MaxNumVertex];
elementtype L[MaxNumVertex];
FindDegreein(ind);//求各个结点的入度
FindDegreeout(outd);//求各个结点的出度
EW(E);//求各个结点的最早发生时间
for(i=0;i<CurrentVertex;i++)
{
L[vertices[i].data] = infinity;//各个结点最迟发生时间的初始化
}
for(i=0;i<CurrentVertex;i++)//将出度为0的顶点入栈
{
if(degreeout(vertices[i].data)==0)
{
s.push(vertices[i].data);
L[vertices[i].data] = E[vertices[i].data];//第一个出度为0的结点的最迟发生时间
}
}
int count =0;//用于统计已经完成的结点数目
while(!s.empty())
{
x = s.top();
count++;//计数
s.pop();
w = firstpre(x);//开始对v的各个前驱顶点的出度-1
while(w!=0)
{
if(L[w]>(L[x]-Getedge(w,x)))
{
L[w] = L[x]-Getedge(w,x);//更新w结点的最迟发生时间
}
if(!(--outd[w]))//若w的出度-1后为0,则入栈
{
s.push(w);
}
w = nextpre(x,w);
}
}
cout<<"E[i],L[i]:"<<endl;
for(i=0;i<CurrentVertex;i++)//输出各个节点的最早发生时间和最迟发生时间
{
cout<<"E["<<i<<"]="<<E[vertices[i].data]<<",L["<<i<<"]="<<L[vertices[i].data]<<endl;
}
vector<elementtype>equal;//记录E[I]=L[I]
for(i=0;i<CurrentVertex;i++)
{
if(E[vertices[i].data]==L[vertices[i].data])
{
equal.push_back(vertices[i].data);
}
}
elementtype start,end;
for(i=0;i<CurrentVertex;i++)//寻找起始结点
{
if(degreein(vertices[i].data)==0)
{
start = vertices[i].data;
break;
}
}
FindDegreeout(outd);//求各个结点的出度
for(i=CurrentVertex-1;i>=0;i--)//寻找终止结点
{
if(degreeout(vertices[i].data)==0)
{
end = vertices[i].data;
break;
}
}
cout<<"CriticalPath is:";
while(start!=end)
{
for(i=0;i<equal.size();i++)//输出关键路径
{
if(Getedge(start,equal[i])!=0)
{
cout<<start<<"->";
start = equal[i];
if(start==end)
{
cout<<start<<endl;
}
break;
}
}
}
return 0;
}
/*
*创建图
*/
elementtype graph::create()
{
int i,VertextNum,ArcNum,v,u,weight;
ifstream infile("file.txt",ios::in);
if(!infile)
{
cerr<<"open error!"<<endl;
exit(1);
}
infile>>VertextNum>>ArcNum;
for( i = 0 ; i < VertextNum ; i ++ )
{
infile>>v;
insertvertex(v);
}
for( i = 0 ; i < ArcNum ; i ++ )
{
infile>>v>>u>>weight;
insertedge(v,u,weight);
}
infile.close();
cout<<"graph create finish!"<<endl<<endl;
return 0;
}
graph::~graph()
{
}
int main()
{
graph g;
g.create();
g.show();
g.CriticalPath();
return 0;
}