数据结构编程题系列(五)图

2,034 阅读16分钟

4.图

4.1 图的遍历

1.求不带权的无向连通图G中距离顶点V最远的一个顶点

​ 可利用广度优先遍历 返回最后一个顶点即可

int BFS(AGraph *G,int v)
{
    ArcNode *p;
    int que[maxsize],front,rear;
    int visit[maxsize];
    front = rear = 0;
    int i,j;
    for(i=0;i<G->n;i++) visit[i] = 0;
    rear = (rear+1)%maxsize;
    que[rear] = v;
    visit[v] = 1;
    while(rear!=front)
    {
        front = (front+1)%maxsize;
        j = que[front];
        p = G->adjlist[j].firstarc;
        while(p)
        {
            if(visit[p->adjvex]==0)
            {
                visit[p->adjvex] = 1;
                rear = (rear+1)%maxsize;
                que[rear] = p->adjvex;
            }
            p = p->nextarc;
        }
    }
    return j;
}

2.判断无向图G是否是一棵树

若边数有n-1 则是 否则 不是

//借助DFS实现
int visit[maxsize];

void DFS(AGraph *G,int v,int &vn,int &en)
{
    ArcNode *p;
    visit[v] = 1;
    vn++;            //顶点数加一
    p = G->adjlist[v].firstarc;
    while(p)
    {
        en++;       //边数加一    这里边数的统计结果是实际边数的两倍
        if(visit[p->adjvex]==0)
            DFS(G,v,vn,en);
        p = p->nextarc;
    }
}

int isTree(AGraph *G)
{
    int i,vn,en;
    vn = en = 0;
    for(i=0;i<G->n;i++) visit[i] = 0;
    for(i=0;i<G->n;i++)             //深度优先遍历来统计图的边数和个数
    {
        DFS(G,i,vn,en); 
    }
    if(vn == G->n && en/2 == G->n-1)
        return 1;
    return 0;
}

4.2 图的存储

4.2.1 邻接表存储

1.用邻接表储存无向图算法

​ --有向图时也是一样 只不过边结点只插入一次即可

//用邻接表储存无向图算法--有向图时也是一样 只不过边结点只插入一次即可
void makeAGraph(AGraph *g)
{
    int i,j,k,n,e;
    cin>>n>>e;        //输入n个顶点和n条边
    int v1,v2;        //两个顶点下标
    //输入顶点信息 建立顶点向量
    for(i=0;i<n;i++)
    {
        cin>>g->adjlist[i].vertex;
        g->adjlist[i].firstarc = NULL;
    }
    //输入边信息 建立边向量
    for(k=0;k<e;k++)
    {
        cin>>v1>>v2;     //输入一条边的两个顶点
        i = 0;
        while(g->adjlist[i].vertex != v1) i++;    //查找v1在顶点表中的下标
        j = 0;
        while(g->adjlist[j].vertex != v2) j++;    //查找v2在顶点表中的下标
        //申请边结点
        ArcNode *p;
        p = (ArcNode *)malloc(sizeof(ArcNode));    //将结点联入
        p->adjvex = j; p->nextarc = g->adjlist[i].firstarc; g->adjlist[i].firstarc = p;
        
        p = (ArcNode *)malloc(sizeof(ArcNode)); 
        p->adjvex = i; p->nextarc = g->adjlist[j].firstarc; g->adjlist[j].firstarc = p;
    }
}

2.有向图的反向邻接表的生成

void deverseGraph(AGprph *g,AGprph *rg)
{
    int i,j;
    for(i=0;i<g->n;i++)  //顶点表的复制
    {
        rg->adjlist[i].vertex = g->adjlist[i].vertex;
        rg->adjlist[i].firstarc = NULL;
    }
    ArcNode *p,*s;
    for(i=0;i<g->e;i++)
    {
        p = g->adjlist[i].firstarc;
        while(p)
        {
            s = (ArcNode*)malloc(sizeof(ArcNode));
            s->adjvex = i;
            j = p->adjvex;
            s->nextarc = rg->adjlist[j].firstarc;
            rg->adjlist[j].firstarc = s;
            p = p->next;
        }
    }
}

4.2.2 邻接矩阵与邻接表转换

1.邻接矩阵转化成邻接表

void AdjMatrixToAdjList( AdjMatrix gm, AdjList gl )
//将图的邻接矩阵表示法转换为邻接表表示法。
{ 
    for (i=1;i<=n;i++) //邻接表表头向量初始化。
    {
        scanf(&gl[i].vertex);
        gl[i].firstarc=null;
    }
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++)
            if (gm[i][j]==1)
            {
                p=(ArcNode *)malloc(sizeof(ArcNode)) ;//申请结点空间。
                p->adjvex=j;//顶点 I 的邻接点是 j
                p->next=gl[i].firstarc;
                gl[i].firstarc=p; //链入顶点 i 的邻接点链表中
            }
}

2.邻接表转化成邻接矩阵

void AdjListToAdjMatrix(AdjList gl, AdjMatrix gm)
//将图的邻接表表示转换为邻接矩阵表示。
{ 
    for (i=1;i<=n;i++) //设图有 n 个顶点,邻接矩阵初始化。
        for (j=1;j<=n;j++)
            gm[i][j]=0;
    for (i=1;i<=n;i++)
    {p=gl[i].firstarc; //取第一个邻接点。
     while (p!=null)
     {
         gm[i][p->adjvex]=1;
         p=p->next;
     }//下一个邻接点
    }
}

4.3 图的顶点和边

4.3.1 图的顶点(度)

1.已知有向图 求各顶点的入度数 (邻接表 邻接矩阵实现)

//求顶点i的入度
int inDegree(AGraph *g,int i)
{
    int j,num;
    ArcNode *p;
    num = 0;
    for(j=0;j<g->n;j++)   //遍历整个邻接表 
    {
        if(i!=j)
        {
            p = g->adjlist[j];
            while(p)
            {
                if(p->adjvex==i) num++;
                p = p->nextarc;
            }
        }
    }
    return num;
}

void AllDegree(AGraph *g)
{
    int i,res;
   	for(i=0;i<g->n;i++)
    {
        res = inDegree(g,i);
        cout<<i<<":"<<res<<endl;
    }
}

2.无向图 求所有顶点的度

3.删除某个顶点(有向图)

//删除结点值为key的结点的算法
//除了删除该顶点外 还要删除相关的边
void deleteNode(AGraph *g,int key)
{
    //查找key顶点下标
    int i,j;
    for(i=0;g->adjlist[i].vertex!=key;i++);
    ArcNode *p,*q,*u;
    p = g->adjlist[i].firstarc;
    //删除所有的出度边
    while(p)                  
    {
        u = p;
        p = p->next;
        free(u);
    }
    //查找所有的入度边并删除
    for(j=0;j<g->n;j++)
    { 
        if(j!=i)
        {
            p = q = g->adjlist[j].firstarc; //设置前驱q
            if(p->adjvex == i)        //第一个邻接点是被删除顶点
            {
                u = p;
                g->adjlist[j].firstarc = p->next;
                p = p->next;
                free(u);
            }
            else                  //第一个邻接点不是被删除顶点
            {
                while(p)
                {
                    if(p->adjvex == i)
                    {
                        u = p;
                        q->nextarc = p->nextarc;
                        free(u);
                        break;
                    }
                    if(p->adjvex > i) p->adjvex--;  //i之后的顶点在向量中的下标前移
                    q->nextarc = p; q=p;p=p->nextarc;
                }
            }
            for(j=i+1;j<n;j++) g[j-1] = g[j];    //删除下标为i的顶点 后面元素前移
        }
    }
}

4.3.2 图的边

1.删除无向图的边(邻接表表示)

void DeletEdge(AdjGraph g, int i,int j)
//在用邻接表方式存储的无向图g中,删除边(i,j)
{
    p=g[i].firstarc;
    pre=null; //删顶点 i 的边结点(i,j),pre 是前驱指针
    while (p)
        if (p->adjvex==j)
        {
            if(pre==null)
                g[i].firstarc=p->next;
            else
                pre->next=p->next;
            free(p);
        }//释放结点空间。
    	else{
            pre=p;
            p=p->next;
        } //沿链表继续查找
    p=g[j].firstarc;
    pre=null; //删顶点 j 的边结点(j,i)
    while (p)
        if (p->adjvex==i)
        {
            if(pre==null)
                g[j].firstarc=p->next;
            else 
                pre->next=p->next;
            free(p);}//释放结点空间。
    	else{
            pre=p;
            p=p->next;
        	} //沿链表继续查找
}

2.删除有向图的边(邻接表表示)

void deleteEdge(AGraph *g,int i,int j)   //删除<i,j>的边
{
    ArcNode *p,pre;
    p = g->adjlist[i].firstarc;
    pre = p;
    p = q = g->adjlist[j].firstarc; //设置前驱q
    if(p->adjvex == j)        //第一个邻接点是被删除顶点
    {
        u = p;
        g->adjlist[j].firstarc = p->next;
        p = p->next;
        free(u);
    }
    else                  //第一个邻接点不是被删除顶点
    {
        while(p)
        {
            if(p->adjvex == i)
            {
                u = p;
                q->nextarc = p->nextarc;
                free(u);
                break;
            }
            q=p;p=p->nextarc;
        }
    }
}

4.3 图的路径

4.3.1 普通路径问题(包括回路)

1.有向图判断vi到vj有无路径

// 1)深度优先遍历的解决方式
//邻接表方式实现
int visit[maxsize];
int havePath(AGraph *g,int vi,int vj) //从vi到vj判断有无路径
{
    if(vi==vj)          //存在路径
        return 1;
    else
    {
        visit[vi] = 1;
        ArcNode *p;
        p = g->adjlist[vi].firstarc;
        while(p)
        {
			if(!visit[p->adjvex] && havePath(g,p->adjvex))
				return 1;
            p=p->nextarc;
        }
        return 0;
    }
}
//邻接矩阵实现方式
int visit[maxsize];
int havePath(MGraph *g,int v1,int v2)
{
    if(v1==v2)    //存在路径
		return 1;
    else
    {
        visit[v1] = 1;
        int i;
        for(i=0;i<g->n;i++)    //扫描v1的邻接顶点
        {
            if(g->edges[v1][i]&&havePath(g,i,v2))
                return 1;      //邻接点进行递归遍历
        }
        return 0;
    }
}


//2)广度优先遍历实现方式
//邻接表方式实现
int havePath(AGraph *g,int v1,int v2)
{
    int visit[maxsize];
    int i;
    for(i=0;i<g.n;i++) visit[i] = 0;
    int que[maxsize],head,rear;
    head = rear = 0;
    rear = (rear+1)%maxsize;
    que[rear] = v1;
    visit[v1] = 1;
    ArcNode *p;
    while(rear!=head)
    {
        head = (head+1)%maxsize;
        p = g->adlist[que[head]].firstarc;
        while(p)
        {
            if(p->adjvex == v2)
                return 1;
            if(!visit[p->adjvex])
            {
                visit[p->adjvex] = 1;
                rear = (rear+1)%maxsize;
                que[rear] = p->adjvex;
            }
            p = p->nextarc;
        }
    }
    return 0;
}
//邻接矩阵实现方式
int havePath(MGraph *g,int v1,int v2)
{
    int que[maxsize],front,rear;
    front = rear = 0;
    int visit[maxsize];
    int i,v;
    for(i=0;i<g.n;i++) visit[i] = 0;
    rear = (rear+1)%maxsize;
    que[rear] = v1;
    visit[v1] = 1;
    while(front!=rear)
    {
        head = (head+1)%maxsize;
        v = que[head];
        for(i=0;i<g.n;i++)
        {
            if(g->edges[v][i]&&i==v2)
                return 1;
            if(g->edges[v][i]&&!visit[i])
            {
                rear = (rear+1)%maxsize;
                que[rear] = i;
                visit[i] = 1;
            }
        }
    }
    return 0;
}


2.判断一个有向图是否存在回路

//通过拓扑排序的方式来判断是否有回路
//邻接表实现方式(天勤的方式)
typedef struct VNode
{
    int indegree;      //用于标记节点的入度
    ArcNode *firstarc;
}
int isCircle(AGraph *g)
{
    int stack[maxsize],top=-1;
    int i,n=0;
    for(i=0;i<g->n;i++)
        if(g->adjlist[i].indegree==0)
            stack[++top] = i;
    ArcNode *p;
    while(top!=-1)
    {
        i = stack[top--];
        n++;
        p = g->adjlist[i].firstarc;
        while(p)
        {
            g->adjlist[p->adjvex].indegree--;
            if(g->adjlist[p->adjvex].indegree == 0)
                stack[++top] = p->adjvex;
            p = p->nextarc;
        }
    }
    if(n==g->n)
        return 0;
    else
        return 1;
}

//邻接矩阵的实现方式
//设置向量indegree 用来存放个顶点的入度值
int isCircle(MGraph *g)
{
    int i,j,top=-1;
    int m=0;
    for(i=0;i<g->n;i++)
    	if(indegree[i]==0)         //建立入度为0的栈 top为栈顶 -1
        {
            indegree[i] = top;
            top = i;
        }
    while(top!=-1)
    {
        m++;j=top;            //取栈顶元素
        top = indegree[top];  //退栈
        for(i=0;i<g->n;i++)
            if(g->edges[j][i])
            {
                indegree[i]--;
                if(indegree[i]==0)
                {
                    indegree[i]=top;top=i;
                }
            }
    }
    if(m<g->n)
        return 0;
    return 1;
}


3.如果r到图G中的每个节点都可以到达,r则为G的根节点,求图G的根节点

void DFS(AGraph *g,int v,int visit[],int &sum)
{
    visit[v] = 1;
    sum++;
    ArcNode *p;
    p = g->adjlist[v].firstarc;
    while(p)
    {
        if(visit[p->adjvex]==0)
            DFS(g,p->adjvex,visit);
    }
}

void PrintRoot(AGraph *g)
{
    int i,sum;;
    for(i=0;i<g.n;i++)
    {
        sum = 0;
        int j;
        for(j=0;j<g.n;j++) visit[j] = 0;
        DFS(g,i,visit,sum);
        if(sum==g->n)
            cout<<i<<endl;
    }
}

4.判断无向图中是否存在一条以V0为起点的包含所有的顶点的简单路径并输出

int visit[maxsize];
int num=0;
int path[maxsize];
void isIncludeALL(AGraph *g,int v0)
{
    visit[v0] = 1;
    path[++num] = v0;
    ArcNode *p;
    if(num==g->n)          //此路径包含所有顶点 则输出
    {
        for(int i=1;i<=num;i++) cout<<path[i]<<;
        exit(0);           //找到后则退出整个程序
    }
    p = g->adjlist[v0].firstarc;
    while(p)
    {
        if(visit[p->adjvex]==0)
            isIncludeALL(g,p->adjvex);
        p = p->nextarc;
    }
    visit[v0] = 0;
    num--;
}

5.判断有向图中是否有从vi到vj的简单路径 若有 则全部打印之

//邻接表的DFS方式递归实现
int path[maxsize],num=-1;       //路径数组
int visit[maxsize];            //标记数组
void PrintPath(AGraph *g,int vi,int vj)
{
    path[++num] = vi;
    visit[vi] = 0;
    if(vi==vj)
    {
        for(int i=0;i<=num;i++)
            cout<<path[i]<<","<<endl;
    }
    ArcNode *p;
    p = g->adjlist[vi].firstarc;
    while(p)
    {
        if(visit[p->adjvex]==0)
            PrintPath(g,p->adjvex,vj);
        p = p->nextarc;
    }
    visit[vi] = 0;                    //释放该节点 使得该节点可重新使用
    num--;
}

//邻接表的DFS方式非递归实现
void PrintPath(AGraph *g,int vi,int vj)
{
    int path[maxsize],num=-1;
    int visit[maxsize];
    int i;
    for(i=0;i<g->n;i++) visit[i]=0;
    path[++num] = vi;
    visit[vi] = 1;
    ArcNode *p;
    while(num!=-1||p)
    {
        p = g->adjlist[path[num]].firstarc;       //第一个临接定点
        while(p!=NULL && visit[p->adjvex]==1) p=p->next;  //下一个访问顶点
        if(p==NULL) 
        {
            i = path[num];
            visit[i] = 0;     //此句是我另加上去的 1800上没有 我感觉得加上 因为该节点或许以后可以							  //重新使用  不知道对不对
            num--; 
        }                      //退栈
        else
        {
            i = p->adjvex;
            if(i==vj)
            {
                for(int i=0;i<=num;i++)
            		cout<<path[i]<<","<<endl;
            }
            else
            {
                visit[i] = 1;
                path[++num] = i;
            }
        }
    }
}

6.根到叶子节点的最大距离被称为树的半径 给定一个无向连通图 写一个算法以找出半径最小的生成树 1800的最后一题 (参考书上的答案怎么感觉怪怪的啊?)

4.3.2 最短路径

​ 1)直接用迪杰斯特拉算法解决 1800 P146 T32

​ 2)直接用Floyd算法解决 1800 P146 T33 T34

//1800 P146 T34
void Floyd(MGraph *g,int A[][maxsize])    //因本题没有求路径 所以省略了path数组
{
    int i,j,k;
    for(i=0;k<g->n;k++)                   //初始化A数组
    	for(j=0;k<g->n;k++)
            A[i][j] = g->adges[i][j];
    
    for(k=0;k<g->n;k++)
    	for(i=0;k<g->n;k++)
            for(j=0;k<g->n;k++)
                if(A[i][j]>=A[i][k]+A[k][j])
                    A[i][j]=A[i][k]+A[k][j];
}
int ShortPath(MGraph *g)       //返回医院应该建立位置的下标
{
    int A[maxsize][maxsize];
    Floyd(g,A);
    int s,i,j,k,m;
    m = INF;             //等于世界上最大的值
   	for(i=0;i<g->n;i++)
    {
        s=0;
        for(j=0;j<g->n;j++)
            if(A[i][j]>s)
                s = A[i][j];
        if(m>s)
        {
            m=s;k=i;      //K记下出发点 也就是医院该建立的位置
        }
    }
    return k;
}

3)如果图的每个边的长度相等时 适合用广度优先遍历算法解决

1.求距离vo的最短路径长度为K的所有顶点 (以弧数为单位)

void findPathToK(AGraph *g,int v0,int k)
{
    int que[maxsize],head=0,rear=0;
    int visit[maxsize];
    int t,level,flag=0;
    que[rear++] = v0;
    t=rear;
    level = 1;
    visit[v0] = 1;
    ArcNode *p;
    while(front!=rear&&level<=K+1)
    {
        v = Q[++front];
        p = g->adjlist[v].firstarc;
        while(p!=NULL)                //证明邻接顶点存在
        {
            if(visit[p->adjvex]==0)
            {
                que[++rear] = p->adjvex;
                visit[p->adjvex] = 1;
                if(level==K+1)
                {
                    //打印
                    cout<<p->adjvex<<endl;
                    flag = 1;
                }
            }
            p = p->nextarc;
        }//while
        if(front==t)
        {
            level++;t=rear;
        }
    }//while
    if(flag==0)            //没有找到
        return 0;
    return 1;
}

2.求图的中心点的算法。设V是有向图G的一个顶点,我们把V的偏心度定义为:max{从w到v的最短距离|w是g中所有顶点},如果v是有向图G中具有最小偏心度的顶点,则称顶点v是G的中心点。

​ 分析:利用 FLOYD 算法求出每对顶点间的最短路径矩阵 w,然后对矩阵 w,求出每列 j 的最大值,得到顶点 j 的偏心度。然后在所有偏心度中,取最小偏心度的顶点 v 就是有向图的中心点。

void FLOYD_PXD(AdjMatrix g)
//对以带权邻接矩阵表示的有向图 g,求其中心点。
{
    AdjMatrix w=g ; //将带权邻接矩阵复制到 w。
    for (k=1;k<=n;k++) //求每对顶点间的最短路径。
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(w[i][j]>w[i][k]+w[k][j])
                    w[i][j]=w[i][k]+w[k][j];
    v=1;
    dist=MAXINT; //中心点初值顶点 v 为1,偏心度初值为机器最大数。
    for(j=1;j<=n;j++)
    {s=0;
     for(i=1;i<=n;i++)
         if(w[i][j]>s)
             s=w[i][j]; //求每列中的最大值为该顶点的偏心度。
     if(s<dist)
     {dist=s; 
      v=j;}//各偏心度中最小值为中心点。
}
 printf( "有向图 g 的中心点是顶点%d,偏心度%d\n",v,dist);
}

3.图G有n个点,利用从某个源点到其余各点最短路径算法思想,设计一产生G的最小生成树的算法。

​ 分析:按 Dijkstra 路径增序求出源点和各顶点间的最短路径。本题是求出最小生成树,即以源点为根,其路径权值之和最小的生成树。在确定顶点的最短路径时,总是知道其(弧出自的)前驱(双亲)顶点,我们可用向量 p[1..n]记录各顶点的双亲信息,源点为根,无双亲,向量中元素值用-1 表示。

void Shortest_PTree ( AdjMatrix G, vertype v0)
//利用从源点 v0 到其余各点的最短路径的思想,产生以邻接矩阵表示的图 G 的最小生成树
{
    int d[] ,s[] ; //d 数组存放各顶点最短路径,s 数组存放顶点是否找到最短路径。
    int p[] ; //p 数组存放顶点在生成树中双亲结点的信息。
    for(i=1;i<=n;i++)
    {d[i]=G[v0][i]; s[i]=0;
     if(d[i]<MAXINT)
         p[i]=v0; //MAXINT 是机器最大数,v0 是 i 的前驱(双亲)。
     else p[i]=-1;
    }// for //i 目前无前驱,p 数组各量初始化为-1。
    s[v0]=1; d[v0]=0; p[v0]=-1; //从 v0 开始,求其最小生成树。
    for(i=1;i<n;i++)
    {mindis=MAXINT;
     for(j=1;j<=n;j++)
         if(s[j]==0 && d[j]<mindis)
         { u=j; mindis=d[j];}
     s[u]=1; //顶点 u 已找到最短路径。
     for (j=1;j<=n;j++) //修改 j 的最短路径及双亲。
         if (s[j]==0 && d[j]>d[u]+G[u][j])
         {d[j]=d[u]+G[u][j]; p[j]=u;}
    }
    for(i=1;i<=n;i++) //输出最短路径及其长度,路径是逆序输出。
        if(i!=v0)
        {pre=p[i];
         printf( "\n 最短路径长度=%d,路径是:%d,",d[i],i);
         while (pre!=-1)
         { printf( ",%d",pre); pre=p[pre];} //一直回溯到根结点。
        }
}

4.3.3 最长路径

1)广度优先遍历解决

1.求有向无环图的最长路径 每条弧的长度均为一

int findLongPath(AGraph *g,int v0)
{
    int que[maxsize],front=0,rear=0;
    int t,level=1,v;
    int visit[maxsize];
    for(int i=0;i<g->n;i++) visit[i] = 0;
    visit[v0] = 1;
    que[++rear] = v0;
    t = rear;
    ArcNode *q;
    while(front!=rear)
    {
     	v = que[++front];
        q = g->adjlist[v].firstarc;
        while(q)
        {
            if(visit[q->adjvex]==0)
            {
                que[++rear] = q->adjvex;
                visit[q->adjvex] = 1;
            }
            q = q->nextarc;
        }
        if(front == t)
        {
            level++;t=rear;
        }
    }
    return level-1;
}

int longestPath(AGraph *g)             返回图的最长路径长度
{
    int i,m,j;
    m = 0;
    for(i=0;i<g->n;i++)
    {
        j = findLongPath(g,i);
        if(i>m) m = j;
    }
    return m;
}

2)拓扑排序解决

1.用拓扑排序求图的最长路径的算法

//此算法我自己写的 或许还不一定对。。。
typedef struct
{
    ArcNode *firstarc;
    int indegree;      //每个顶点的入度数
}VNode;               //图的顶点结构

typedef struct
{
    int next;
    int w;            //与下一邻接点所构成的边的权值大小
}Node;                //数组元素的结构  (采用树的储存方式来记录节点路径)

void topSort(AGraph *g)
{
    Node set[maxsize];
    //寻找入度为零的顶点
    int i,sign;
    int stack[maxsize],top=0;          //栈储存顶点下标
    for(i=0;i<g->n;i++)
    {
        if(g->adjlist[i].indegree==0)
        {
            stack[++top] = i;
            set[i].next = -1;
        } 
    }
    sign = top;
    ArcNode *p;
    int m,maxadj;
    while(top!=-1)
    {
        i = stack[top--];
        p = g->adjlist[i].firstarc;
        m=0;
        while(p)
        {
            g->adjlist[i].indegree--;
            if(g->adjlist[i].indegree==0)
            {
                if(m<p->weight)
                {
                    m = p->weight;
                    maxw = p->weight;
                }
             	stack[++top] = p->adjvex;
            }
        }
        set[i].next = minadj;
        set[i].w = m;
        set[minadj] = -1;
    }
    
    //从所有路径中选择最长的
    int j,flag,result=0;
    for(i=1;i<=sign;i++)
    {
        j=i;m=0;
        while(j!=-1)
        {
            m+=set[j].w;
            j = set[j].next;
        }
        if(result<m)
        {
         	result = m;
            flag = i;
        }
    }
    //输出相应节点
    while(flag!=-1)
    {
     	cout<<flag<<","<<endl;
        flag = set[flag].next;
    }
}

4.4 连通分量/强连通分量

1.已知无向图G 求图的连通分量的算法,同时输出每一个连通分量顶点

int linkNum()
{
    int k=0;
    for(int i=0;i<g->n;i++)
    {
        if(visit[i]==0)
        {
            k++;
            printf("%d\n",i);//输出顶点
            DFS(i);  //或者BFS
        }
    }
    return k;
}

4.5 拓扑排序

1.利用深度优先遍历方法,对该图中结点进行拓扑排序。

​ 分析:在遍历过程中,每访问一个顶点,就将其邻接到的顶点的入度减一,并对其未访问的、入度为0的邻接到的顶点进行递归。