拓扑排序入门 基础

Posted 1starfish

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序入门 基础相关的知识,希望对你有一定的参考价值。

早上学了拓扑排序中最基础的一题,教的是用vector写的 然后自己刚刚用链式前向星写了一遍

拓扑排序就是先找出度为0的点然后放入队列,再把与这个点相连的点的度减一,如果度变成了0就在放进队列里面,直到队列变为空。

判断这个图是否无环 就用sum=0,每次进去就sum++,如果最后sum==n说明是无环的。

拓扑排序的裸题:

确定比赛名次

TimeLimit: 2000/1000 MS (Java/Others)  MemoryLimit: 65536/32768 K (Java/Others)
 
 
Problem Description
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。 
Input
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。 
Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。 

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。 
SampleInput
4 3
1 2
2 3
4 3
SampleOutput
1 2 4 3

第一种 vector写法:
#include<stdio.h>
#include<string>
#include<string.h>
#include<set>
#include<queue>
#include<math.h>
#include<stack>
#include<vector>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define ll long long
#define mes(x,a) memset(x,a,sizeof(x))
const int maxn=1e3+3;
const int inf=0x3f3f3f3f;
vector<int>a[maxn];
int n,m;
int degree[maxn];

void init()
{
    mes(degree,0);
    for(int i=0; i<=n; i++)
        a[i].clear();
}
void topo()
{
    int i,j,t;
    priority_queue<int>que;
    for(int i=1; i<=n; i++)
        if(degree[i]==0)
            que.push(-i);
    int flag=1;
    while(!que.empty())
    {
        if(!flag)
            printf(" ");
        if(flag)
            flag=0;
        int now=-que.top();
        que.pop();
        printf("%d",now);
        for(int i=0; i<a[now].size(); i++)
        {
            int y=a[now][i];
            degree[y]--;
            if(degree[y]==0)
                que.push(-y);
        }
    }
    puts("");
}
int main()
{
    int i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(i=0; i<m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            a[u].push_back(v);
            degree[v]++;
        }
        topo();
    }
    return 0;
}

第二种链式前向星写法:

#include<stdio.h>
#include<string>
#include<string.h>
#include<set>
#include<queue>
#include<math.h>
#include<stack>
#include<vector>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn=1e3+5;
int n,m;
int first[maxn],sign;
int degree[maxn];
struct Edge
{
    int to;
    int w;
    int next;
} edge[maxn];
void init()
{
    sign=0;
    memset(first,-1,sizeof(first));
    memset(edge,0,sizeof(edge));
}
void add_edge(int u,int v,int w)
{
    edge[sign].to=v;
    edge[sign].w=w;
    edge[sign].next=first[u];
    first[u]=sign++;
}
void topo()
{
    priority_queue<int,vector<int >, greater<int > >que; ///小根堆
    for(int i=1; i<=n; i++)
    {
        if(degree[i]==0)
            que.push(i);
    }
    int flag=0;
    while(!que.empty())
    {
        int now=que.top();
        que.pop();
        if(flag==1)
        {
            printf(" ");
        }
        flag=1;
        printf("%d",now);
        for(int i=first[now]; ~i; i=edge[i].next)
        {
            int to=edge[i].to;
            degree[to]--;             ///与now相连的点的度减一,如果==1就放进队列
            if(degree[to]==0)
            {
                que.push(to);
            }
        }
    }
    puts("");

}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        init();
        for(int i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            add_edge(u,v,1);
            degree[v]++;///度增加
        }
        topo();
    }
}

 





以上是关于拓扑排序入门 基础的主要内容,如果未能解决你的问题,请参考以下文章

ACM入门之拓扑排序

拓扑排序((算法竞赛入门经典)刘汝佳)

POJ 2367 Genealogical tree 拓扑排序入门题

LeetCode拓扑排序

图论基础——邻接链表存图+拓扑排序

逆向拓扑排序