• 拓扑排序


    拓扑排序

    定义:拓扑排序是指在有向无环图中,将所有的结点进行排序,最终得出的序列称为拓扑序。

    先来看一个模板代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn=1e5+10;
    int n,m,tot=0,head[maxn],seq[maxn],d[maxn];
    struct node
    {
        int nex,to;    
    }edge[maxn];
    void init()
    {
        tot=0;
        memset(head,-1,sizeof(head));
        memset(seq,0,sizeof(seq));		//保存拓扑排序的结点
        memset(d,0,sizeof(d));			//保存每个结点的入度
    }
    void add(int from,int to)
    {
        edge[++tot].to=to;
        edge[tot].nex=head[from];
        head[from]=tot;
    }
    void topsort()
    {
        queue<int> q;           
        //如果编号要按顺序输出可有priority_queue<int,vector<int>,greater<int> >
        for(int i=1;i<=n;++i)
            if(!d[i])   q.push(i);
        int cnt=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            seq[++cnt]=u;
            for(int i=head[u];i!=-1;i=edge[i].nex)
                if(--d[edge[i].to]==0)   q.push(edge[i].to);
        }
        if(cnt!=n){
            printf("-1
    ");     //存在环
            return;
        }
        for(int i=1;i<=n;++i){
            printf("%d%c",seq[i],i==n?'
    ':' ');
        }
    }
    
    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(u,v);
                d[v]++;
            }
            topsort();
        }
    }
    

    【题意】:有n个小球和m个要求,所有小球的重量在1~n之间,每个要求的格式为 a b 表示a比b轻,输出最小的字典序的组合。

    思路:将所有小球的出度表示出来,用大根堆的优先队列将所有小球出度为0的球装进去,每次弹出一个编号最大的将剩余的最大重量给它贪心即可;show code:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    const int maxn=210;
    int od[maxn],arr[maxn][maxn],T,n,m,seq[maxn];
    void topsort()
    {
        priority_queue<int> q;
        int tot=n;
        for(int i=1;i<=n;++i)
            if(od[i]==0)    q.push(i);
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            seq[u]=tot--;
            for(int i=1;i<=n;++i){
                if(arr[i][u]){
                    od[i]--;
                    if(od[i]==0)    q.push(i);
                }
            }
        }
        if(tot){
            printf("-1
    ");
            return;
        }
        for(int i=1;i<=n;++i){
            printf("%d%c",seq[i],i==n?'
    ':' ');
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d %d",&n,&m);
            for(int i=1;i<=n;++i){
                for(int j=1;j<=n;++j){
                    arr[i][j]=0;
                    od[i]=seq[i]=0;
                }
            }
            for(int i=1;i<=m;++i){
                int a,b;
                scanf("%d %d",&a,&b);
                if(!arr[a][b]){
                    od[a]++;
                    arr[a][b]=1;
                }
            }
            topsort();
        }
    }
    
  • 相关阅读:
    CH和CN图标去除及语言栏变短
    vim命令学习总结
    《Applications=Code+Markup》读书札记(2)——创建一个简单的 WPF 程序的代码结构及关于 Window 实例位置设置问题
    linux 开机时自动挂载分区
    Windows/linux双系统的时间修改问题
    关于RHEL6.1你可能想知道的那点事
    C语言的重要概念
    sprintf你知道多少
    《Applications=Code+Markup》读书札记(1)——一个简单的 WPF 程序
    Linux命令——tar
  • 原文地址:https://www.cnblogs.com/StungYep/p/12252228.html
Copyright © 2020-2023  润新知