• hdu2647 逆拓扑,链式前向星。


    原文地址


    题目分析

    题意

    老板发工资,但是要保证发的工资数满足每个人的期望,比如A期望工资大于B,只需比B多1元钱即可。老板发的最低工资为888元。输出老板最少发的工资总数,若是无法满足大家的期望,则输出-1。

    分析

    很明显这是一个拓扑问题,若存在环则无法满足大家的期望。若按常理,A>B,则可能会建立A指向B的有向边。此题不然,因为我们只知道最少的钱数是888,所以从小到大进行拓扑排序更为恰当。所以是建立B指向A的有向边。此之为逆拓扑排序。因为这样处理后排序的结果与原先拓扑排序的顺序相反。

    以图论观点来看,若为邻接矩阵存储就视作了矩阵的逆置。

    链式前向星

    链式前向星是图的一种存储方式,其实质是邻接表的静态存储。关于链式前向星的更多介绍,可移步《深度理解链式前向星》

    吐槽,链式前向星并非学术上的术语,貌似是国内网友的起名智慧。。因此国外没有这样的术语。不过这个词在国内还是有认可度的。

    我的代码

    用了点小技巧,比如static变量,还有重载构造函数等等。因此跑了359ms(g++)43ms(c++)。。囧。重度追求效率的童鞋可无视,本代码重在谈思路。

    #include<iostream>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int max_size=10001;
    int n,m;
    int head[max_size];
    int in[max_size];
    int reward[max_size];
    queue<int> q;
    struct Edge
    {
        int to;
        int next;
        Edge(){};
        Edge(int i,int j):to(i),next(j){};
    };
    Edge edges[max_size*2];
    void add(int i,int j)
    {
        static int k=0;
        edges[k].to=j;
        edges[k].next=head[i];
        head[i]=k++;
        if(k==m)
            k=0;
    }
    void topo()
    {
        for(int i=1;i<=n;i++)
        {
            if(in[i]==0)
            {
                reward[i]=0;
                q.push(i);
            }
        }
        int top;
        int to;
        while(!q.empty())
        {
            top=q.front();
            q.pop();
            for(int k=head[top];k!=-1;k=edges[k].next)
            {
                to = edges[k].to;
                in[to]--;
                if(in[to]==0)
                    q.push(to);
                reward[to]=reward[top]+1;//多1块钱就行了。。
            }
        }
        int sum=n*888;
        for(int i=1;i<=n;i++)
        {
            if(reward[i]<0)
            {
                cout<<-1<<endl;//如果奖金(工资)数组reward中还有-1存在,说明有环。
                return;
            }
            sum+=reward[i];
        }
        cout<<sum<<endl;
    }
    int main()
    {
        int i,j;
        while(cin>>n>>m)
        {
            memset(in,0,sizeof in);
            memset(head,-1,sizeof head);
            memset(reward,-1,sizeof reward);
            for(int t=0;t<m;t++)
            {
                cin>>i>>j;
                add(j,i);
                in[i]++;
            }
            topo();
        }
    }
    


  • 相关阅读:
    THUSC2021游记
    CF补题计划
    2020 Petrozavodsk Winter Camp Day5 简要题解
    很“炸”的安卓UI自动化工具
    SQL-关联查询
    MeterSphere接口自动化平台的使用
    Android开发Handler是如何确保UI刷新优先执行的源码解读
    android开发BadTokenException: Unable to add window -- token null is not valid; is your activity running?比较好的解决方法
    Android开发判断是否为鸿蒙系统
    Android性能优化使用自带的Profiler功能分析traceView文件
  • 原文地址:https://www.cnblogs.com/unclejelly/p/4082062.html
Copyright © 2020-2023  润新知