拓扑排序

拓扑排序:

.拓扑序列算法思想

 (1)从有向图中选取一个没有前驱(即入度为0)的顶点,并输出之;

 (2)从有向图中删去此顶点以及所有以它为尾的弧;

    重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。

.代码实现

   采用邻接矩阵实现,map[i][j]=0,表示节点ij没有关联;map[i][j]=1,表示存在边<i,j>,并且j的入度加1;

#include<iostream>//复杂度高

#include<stdlib.h>

#include<stdio.h>

#include<string.h>

#define MAX 100

using namespace std;

void toposort(int map[MAX][MAX],int indegree[MAX],int n)

{

    int i,j,k;

    for(i=1;i<=n;i++) //遍历n

    {

        for(j=1;j<=n;j++) //找出入度为0的节点

        {

            if(indegree[j]==0)

            {

                indegree[j]--;

                cout<<j<<endl;//其中一种拓扑排序

                for(k=1;k<=n;k++) //删除与该节点关联的边

                {

                    if(map[j][k]==1)

                    {

                        indegree[k]--;

                    }

                }

                break;

            }

        }

    }

}

int main(void)

{

    int n,m; //n:关联的边数,m:节点数

    while(scanf("%d %d",&n,&m)==2&&n!=0)

    {

        int i;

        int x,y;

        int map[MAX][MAX]; //邻接矩阵

        int indegree[MAX]; //入度

        memset(map,0,sizeof(map));

        memset(indegree,0,sizeof(indegree));

        for(i=1;i<=n;i++)

        {

            scanf("%d %d",&x,&y);

            if(!map[x][y])

            {

                map[x][y]=1;

                indegree[y]++;

            }

        }

        toposort(map,indegree,m);

    }

    return 0;

}

复杂度低:

拓扑排序合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>

#include <queue>

#define LL long long

using namespace std;

const int INF = 1e9+7;

const int VM = 503;//点的个数

struct node  //前向星的结构体

{

    int v;//输队编号

    int next;

};

node edge[VM * 4];//结构体数组

int head[VM];//头指针数组

int cnt;//下标

int deg[VM];//入度数组

void toposort(int n)

{

    priority_queue<int, vector<int>, greater<int> > que;//优先队列

    for (int i = 1; i <= n; i++)//找所有点

        if (deg[i] == 0)  //入度为0

        {

            que.push(i);//加入队列

            deg[i]--;//入度 变为-1

        }

    int k = 1;

    while (que.empty() == false)  //队列不为空

    {

        int u = que.top();//取出队首的数

        que.pop();//删除

        printf("%d%c", u, k++ == n ? '\n' : ' ');//输出

        for (int i = head[u]; i != -1; i = edge[i].next)  //与该点相连的

        {

            node e = edge[i];//便于书写

            deg[e.v]--;//点的入度-1

            if (deg[e.v] == 0)//若此点的 入度为0

                que.push(e.v);//放入队列

        }

    }

}

int main()

{

    int n, m;

    int i;

    while (scanf("%d %d", &n, &m) == 2)  //多组输入 ,获取n,m

    {

        memset(head, -1, sizeof(head));//初始化

        memset(deg, 0, sizeof(deg));//初始化

        cnt = 0;//初始化

        while (m--)

        {

            int u, v;

            scanf("%d %d", &u, &v);//获取u,v

            for (i = head[u]; i != -1; i = edge[i].next)//查找重边

                if (edge[i].v == v)//输入重复数据

                    break;//不再储存

            if (i == -1)  //若不是重复数据

            {

                deg[v]++;//加边

                edge[cnt].v = v;

                edge[cnt].next = head[u];

                head[u] = cnt++;

            }

        }

        toposort(n);//调用函数

        bool fla=true;

        for(int i=1; i<=n; i++)

        {

            if(deg[i]>0)

            {

                fla=false;

                break;

            }

        }

        if(!fla)

            printf("youhuan\n");

        else

            printf("meihuan\n");

    }

}

拓扑排序符合条件的排名可能不是唯一的,此时要求输出时编号的队伍在前

#include<stdio.h>

#include<queue>

#include<algorithm>

#include<string.h>

#include<iostream>

#include<vector>

using namespace std;

int main()

{

int rd[10000];

    int top[10000];

    vector<int>v[10000];

    queue<int>q;

    int n,m;

    int cot;

    scanf("%d%d",&n,&m);

    //初始化

    memset(rd,0,sizeof(rd));

    for(int i=0;i<=n;i++)

    v[i].clear();

    cot=0;

    //输入边

    int x,y;

    for(int i=0;i<m;i++)

    {

    scanf("%d%d",&x,&y);

    rd[x]++;

    v[y].push_back(x);

    }

    //找到入度为0入队列

    for(int i=1;i<=n;i++)

    {

    if(rd[i]==0)

    {

    q.push(i);

    rd[i]--;

    top[cot++]=i;

    }

    }

    while(!q.empty())

    {

    int k=q.front();

    printf("%d\n",k);

    q.pop();

 

    for(int i=0;i<(int)v[k].size();i++)

    {

    int tep=v[k][i];

    rd[tep]--;

    if(rd[tep]==0)

    {

    q.push(tep);

    top[cot++]=tep;

    }

    }

    }

    bool fla=true;

    for(int i=1;i<=n;i++)

    {

    if(rd[i]>0)

    {

    fla=false;

    break;

    }

    }

    if(!fla)

    printf("youhuan\n");

    else

    printf("meihuan\n");

}

 

练习:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105824#overview

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值