活动网络——AOV网络

一般一个工程可以分成若干个子工程,这些子工程称为活动。实际上,可以用有向图来表示一个工程,用有向边<u,v>表示活动u必须先于活动v完成。这种有向图叫做顶点表示活动的网络,记作AOV网络(Activity On Vertices)。u成为v的直接前驱,v叫做u的直接后继,如果存在路径<u,u1,u2,u3.......v>,则称u是v的前驱,v是u的后继。任何活动不能以他自己为前驱或者后继,这种特性称为反自反性,AOV网络中不能出现有向回路。不含有向回路的有向图称为有向无环图,对于给定的AOV网络,必须先判断它是否是有向无环图。

拓扑排序:判断有向无环图的方法是对AOV网络构造它的拓扑有序序列,即将各个顶点排列成一个线性有序的序列。

实现方法:(1)从AOV网络中选取一个入度为0的顶点并输出

(2)从AOV网络中删除该顶点及该顶点发出的所有边

(3)重复步骤(1)(2),直到找不到入度为0的顶点

按照上述方法进行拓扑排序,其结果有两种情形:(1)所有的顶点都被输出,也就是整个拓扑排序完成了 (2)仍有顶点没有被输出,但剩下的图中再也没有入度为0的顶点,这样拓扑排序就不能再继续进行下去了,说明此图是有向环图。

例题:对输入的有向图进行拓扑排序,并输出一个拓扑排序序列。如果存在有向环,则给出提示信息。             

输入描述:先输入顶点数n和边数m,然后输出m条边。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 10
struct ArcNode
{
    int to;
    ArcNode *next;
};
int n,m;
ArcNode *list[MAXN];
int count[MAXN];
char output[100];
void TopSort();
int main()
{
    int i,j;
    int u,v,w;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0) break;
        memset(list,0,sizeof(list));
        memset(count,0,sizeof(count));
        memset(output,0,sizeof(output));
        ArcNode *temp;
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            u--;
            v--;
            count[v]++;
            temp=new ArcNode;
            temp->to=v;
            temp->next=NULL;
            if(list[u]==NULL)
                list[u]=temp;
            else
            {
                temp->next=list[u];
                list[u]=temp;
            }
        }
        TopSort();
        for(i=0;i<n;i++)
        {
            temp=list[i];
            while(temp!=NULL)
            {
                list[i]=temp->next;
                delete temp;
                temp=list[i];
            }
        }
    }
    return 0;
}
void TopSort()///拓扑排序
{
    int i,j,top=-1;
    ArcNode *temp;
    bool bcycle=false;/// 是否存在有向环的标志
    int pos=0;///写入output数组的位置
    for(i=0;i<n;i++)///入度为0的点入栈
    {
        if(count[i]==0)
        {
            count[i]=top;
            top=i;
        }
    }
    for(i=0;i<n;i++)
    {
        if(top==-1)///栈为空,存在有向回路
        {
            bcycle=true;
            break;
        }
        else
        {
            j=top;///栈顶点j出栈
            top=count[top];
            pos+=sprintf(output+pos,"%d ",j+1);///返回值为这一次写入的字符串的长度
            temp=list[j];
            ///遍历顶点j的边链表,每条出边的终点入度减一
            while(temp!=NULL)
            {
                int k=temp->to;
                count[k]--;
                if(count[k]==0)
                {
                    count[k]=top;
                    top=k;
                }
                temp=temp->next;
            }
        }
    }
    if(bcycle)
        printf("Network has a cycle\n");
    else
    {
        int len=strlen(output);
        output[len-1]=0;///去掉最后的空格
        printf("%s\n",output);
    }
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值