众所周知,度度熊喜欢各类体育活动。 

今天,它终于当上了梦寐以求的体育课老师。第一次课上,它发现一个有趣的事情。在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的ID,从1到NN,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排队结果可以使得所有同学的评价分数和最大。 

Input第一行一个整数TT,表示T(1≤T≤30)T(1≤T≤30) 组数据。 

对于每组数据,第一行输入两个整数NN和M(1≤N≤100000,0≤M≤100000)M(1≤N≤100000,0≤M≤100000),分别表示总人数和某些同学的偏好。 

接下来MM行,每行两个整数AA 和B(1≤A,B≤N)B(1≤A,B≤N),表示ID为AA的同学不希望ID为BB的同学排在他(她)之前。你可以认为题目保证至少有一种排列方法是符合所有要求的。 
Output对于每组数据,输出最大分数 。Sample Input

3
1 0
2 1
1 2
3 1
3 1

Sample Output

1
2
6
对于这个题目来说,显然可以看出这是有限制关系的偏序排序题目,拓扑排序的思想自然而然,想到思路并不难没重点是如何处理程序并将程序写出来;
根据个人习惯,把理解加在代码注释里面。
#include <iostream>
#include <string>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100010;
const int inf  = 0x3f3f3f3f3f;
vector<int> G[maxn];//由于直接用int G[maxn][maxn] 会占用大内存,有可能会爆
int indegree[maxn];//这是对点的入度标记
int main()
{
    int T;
    scanf("%d",&T);
    int n,m;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(indegree,0,sizeof(indegree));//清空处理,同下
        memset(G,0,sizeof(G));//第二阶段代码会对这一点进行优化;
        int u,v;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            G[u].push_back(v);//和点u,存在偏序关系的点 v,压入
            indegree[v]++;//哈希图特点,偏序关系,由u->v,点v的入度++,不需要考虑出度
        }//具体可以参考另一篇博文
        priority_queue<int> que;//优先队列对压入的点进行维护
        //优先队列默认是大的在前,也就是降序
        for(int k=1;k<=n;k++)
            if(!indegree[k]) que.push(k);//先将没有入度的点压入,
        //没有入度的点,也就是不存在以该点为终点的偏序关系,对整体排序没有影响
        //在哈希图上体现就是(假设哈希图由下往上绘制),这个点是悬挂点,极小点(离散数学)
        long long res=0;//long long 保险,看题目吧
        int u_num=inf;//考虑程序的鲁棒性,定义为无限大
        while(!que.empty())//队列的维护+模拟过程
        {
            int num=que.top();//头,是不是有点像bfs,这就对了
            que.pop();//就按照bfs代码方式搞下去,部分改变
            u_num=min(u_num,num);
            res+=u_num;
            for(int i=0;i<G[num].size();i++)
            {
                int v=G[num][i];//这是对该点排序后,删除所有把该点作为起点的线段
                //也可以理解为,除去哈希图上的这个点->哈希图不允许悬挂边的存在
                indegree[v]--;//对应的终点入度--
                if(!indegree[v])//入度为0,对后续排序没影响,选择压入
                    que.push(v);
            }
        }
        printf("%lld\n",res);//输出总花费
    }
}

  运行702ms;

其实可以看出来memset遍历清空费的时间是比较大的,可以根据vector特点修改下(借鉴了求前辈的博文)

#include <iostream>
#include <string>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100010;
const int inf  = 0x3f3f3f3f3f;
vector<int> G[maxn];
int indegree[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    int n,m;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) {
            indegree[i] = 0;
            G[i].clear();
        }
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            indegree[v]++;
        }
        priority_queue<int> que;
        for(int k=1;k<=n;k++)
            if(!indegree[k]) que.push(k);
        long long res=0;
        int u_num=inf;
        while(!que.empty())
        {
            int num=que.top();
            que.pop();
            u_num=min(u_num,num);
            res+=u_num;
            for(int i=0;i<G[num].size();i++)
            {
                int v=G[num][i];
                indegree[v]--;
                if(!indegree[v])
                    que.push(v);
            }
        }
        printf("%lld\n",res);
    }
}

  608ms;确实,有点效果;

不知道之前我的拓扑你们看了没,请看如下代码;

#include <iostream>
#include <string>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 100010;
const int inf  = 0x3f3f3f3f3f;
vector<int> G[maxn];
int indegree[maxn];
priority_queue<int> que;
void combine(int a,int b)
{
    G[a].push_back(b);
    indegree[b]++;
    return;
}
void del_gre(int num)
{
    for(int i=0;i<G[num].size();i++)
    {
        int v=G[num][i];
        indegree[v]--;
        if(!indegree[v])
           que.push(v);
    }
    return;
}
int main()
{
    int T;
    scanf("%d",&T);
    int n,m;
    while(T--)
    {
        while(!que.empty())
            que.pop();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) {
            indegree[i] = 0;
            G[i].clear();
        }
        int u,v;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            combine(u,v);
        }

        for(int k=1;k<=n;k++)
            if(!indegree[k]) que.push(k);
        long long res=0;
        int u_num=inf;
        while(!que.empty())
        {
            int num=que.top();
            que.pop();
            u_num=min(u_num,num);
            res+=u_num;
            del_gre(num);
        }
        printf("%lld\n",res);
    }
}

  根据我上个关于拓扑理解写的

670ms;

最后来一句,求关注~’

拓扑排序 HDU - 5695的更多相关文章

  1. 拓扑排序 - hdu 1285(普通和优先队列优化)

    2017-09-12 19:50:58 writer:pprp 最近刚开始接触拓扑排序,拓扑排序适用于:无圈图的顶点的一种排序, 用来解决有优先级别的排序问题,比如课程先修后修,排名等. 主要实现:用 ...

  2. 拓扑排序 --- hdu 4948 : Kingdom

    Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  3. HDU - 5695 Gym Class 【拓扑排序】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5695 思路 给定一些关系 进行拓扑排序 但是有一个要求 对于哪些没有确切的位置的点 要按照ID大小 I ...

  4. HDU 5695 ——Gym Class——————【贪心思想,拓扑排序】

    Gym Class Time Limit: 6000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  5. 2016"百度之星" - 初赛(Astar Round2A)HDU 5695 拓扑排序+优先队列

    Gym Class Time Limit: 6000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  6. HDU - 5695 Gym Class (优先队列+拓扑排序)

    题意:有N个人,每个人的ID为1~N,部分同学A不希望部分同学B排在他之前,排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数.在满足这个前提的情况下,将N个人排 ...

  7. HDU 4857 逃生 (反向拓扑排序 & 容器实现)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  8. ACM: HDU 1285 确定比赛名次 - 拓扑排序

     HDU 1285 确定比赛名次 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  9. ACM: hdu 2647 Reward -拓扑排序

    hdu 2647 Reward Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Des ...

随机推荐

  1. C++Builder中MessageBox的基本用法

    C++Builder中MessageBox的基本用法 返回值:IDYES=Application->MessageBox("","",MBYESNO) i ...

  2. Rundeck部署和基本使用

    rundeck 介绍 Rundeck 是一款能在数据中心或云环境中的日常业务中使程序自动化的开源软件.Rundeck 提供了大量功能,可以减轻耗时繁重的体力劳动.团队可以相互协作,分享如何过程自动化, ...

  3. spring 内部工作机制(二)

    本章节讲Spring容器从加载配置文件到创建出一个完整Bean的作业流程及参与的角色. Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表, ...

  4. JS使用默认图片代替页面上无法显示的图片

    1.js方法: function replaceErrorImg(obj) { obj.src="images/common/error.bmp"; } 2.jquery绑定 $( ...

  5. Python系列之正则表达式详解

    Python 正则表达式模块 (re) 简介 Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,和 Perl 脚本的正则表达式功能类似,使用 ...

  6. Unity3D - Animator Controller循环依赖

    问题 假设有2个Animator Controller,分别命名为TestControllerLhs.controller以及TestControllerRhs.controller.在TestCon ...

  7. JDownload: 一款可以从网络上下载文件的小程序第四篇(整体架构描述)

    一 前言 时间过得真快,距离本系列博客第一篇的发布已经过去9个月了,本文是该系列的第四篇博客,将对JDownload做一个整体的描述与介绍.恩,先让笔者把记忆拉回到2017年年初,那会笔者在看Unix ...

  8. Dapper数据库相关操作

    using System; using System.Data; using System.Configuration; using System.Data.SqlClient; namespace ...

  9. (10.16)java小作业!

    相信大家刚刚学习java多多少少都会写一些java的基础编程来练练手感,我也不例外!今天想和大家分享一下我最近所接触到的比较有趣的java小编程! 已知a已被赋值,b已被赋值,请编写java程序实现a ...

  10. MyBatis开发中解决返回字段不全的问题

    场景重现: mybatis 在查询的时候,可以返回Map,但是一旦这个字段为空(null)的时候,map里就没有了.我用的是mysql数据库,除了在查询语句上做ifnull判断给它默认值外,有没的别的 ...