这里是一些图的一些基础题目。
首先是dijkstra算法,也就是dijkstra求最短路径的问题。
这个一般是来解决 一个点到其他点最短路径的问题。
具体的做法是,设置一个数组d表示,每一个点到该点的最短距离。edge表示邻接矩阵,d初始化为
d[i]=edge[i][v],然后每次找d数组中最小的那个值,并且标记,然后更新d数组,假如新添加了一个k点,则对每一个可以比较的d,去进行d[k]+edge[k][i];
然后是floyd求最短路径,这个是求任意两点之间的最短距离。
方法是冬二维数组d[i][j]来表示i点到j点的最短距离,初始化时等于edge[i][j]。但要明白的是i到j点的最短距离可能是中间先到达别的一系列的点然后再到达k点,所以找出所有的情况。
void floyd()
{
int i,j,k;
for(i=0;i<v;i++)
for(j=0;j<v;j++)
{
d[i][j]=edge[i][j];
if(d[i][j]!=999)
p[i][j]=ver[i]+ver[j];
else
p[i][j]="";
}
for(k=0;k<v;k++)
for(i=0;i<v;i++)
for(j=0;j<v;j++)
{
if(d[i][k]+d[k][j]<d[i][j])
{
d[i][j]=d[i][k]+d[k][j];
p[i][j]=p[i][k]+ver[j];
}
}
}
kruskal算法求最小生成树
这种方法是按找边方法的,先找最短的那一条边,将两个顶点用并查集的方法合并为一条边,然后再去找最短的边,如果两个顶点分不是一个 根的话就合并,直到找到n-1条边为止
int inset(int v1)//找根
{
int x=v1;
while(p[x]>0)
x=p[x];
return x;
}
struct v
{
int f,to;
int w;
}e[502];
bool cmp(v a1,v a2)//按权值排序
{
if(a1.w==a2.w)
return a1.f<a2.f;
else
return a1.w<a2.w;
}
void kryskal()
{
for(int i=1;i<=vnum;i++)
p[i]=0;
int num=1,v1,v2;
for(int i=1;num<vnum;i++)
{
v1=inset(e[i].f);
v2=inset(e[i].to);
if(v1!=v2)
{
cout<<e[i].f<<" "<<e[i].to<<" ";
p[v1]=v2;
num++;
}
}
}
prim算法求最小生成树
这个是按找点的方法来建树,首先随便添加一个点定义l数组用来存别的点到该点的距离,找到最短距离,标记并更新,更新的方法是看剩余的点的距离与新加入点的距离比较,较小的取代
void prim(int v)
{
int ad[1000],low[1000];
for(int i=0;i<vnum;i++)
{
low[i]=edge[v][i];
}
low[v]=0;
for(int i=1;i<vnum;i++)
{
int j=MIN(low);
cout<<low[j]<<" ";
low[j]=0;
for(int i=0;i<vnum;i++)
{
if(edge[j][i]<low[i])
{
low[i]=edge[j][i];
}
}
}
}
拓扑排序的输入,先输出入度为零的点然后,把该点到其他点的入度减一,重复就好了
void tsort()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mapp[i][j]==1)
rudu[j]++;
for(int i=1;i<=n;i++)
{
int it=0;
for(int j=1;j<=n;j++)
{
if(rudu[j]==0)
{
it=j;
break;
}
}
rudu[it]=-1;
path[i]=it;
for(int j=1;j<=n;j++)
if(mapp[it][j]==1)
rudu[j]--;
}
}
拓扑图求关键路径
端点为事件,边为活动,用结构体存储w,用qd zd存储每一条边的开始和结束的点。然后去求
每个事件的最早发生时间和最晚发生时间
最早发生时间:首先端点0的最早发生时间是零
其次是其他所有点能到达他的点,的最短时间在加上到达他这个活动的时间的最大值。
最晚发生时间是,这个点能到的所有的店中的最晚发生时间减去活动的最小值
然后去找活动的最早和最晚时间
活动最早时间等于该边边起点的最短事件时间
活动最晚时间等于改变终点的最晚时间减去权值