拓扑排序 HDU - 5695
今天,它终于当上了梦寐以求的体育课老师。第一次课上,它发现一个有趣的事情。在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的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的更多相关文章
- 拓扑排序 - hdu 1285(普通和优先队列优化)
2017-09-12 19:50:58 writer:pprp 最近刚开始接触拓扑排序,拓扑排序适用于:无圈图的顶点的一种排序, 用来解决有优先级别的排序问题,比如课程先修后修,排名等. 主要实现:用 ...
- 拓扑排序 --- hdu 4948 : Kingdom
Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- HDU - 5695 Gym Class 【拓扑排序】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5695 思路 给定一些关系 进行拓扑排序 但是有一个要求 对于哪些没有确切的位置的点 要按照ID大小 I ...
- HDU 5695 ——Gym Class——————【贪心思想,拓扑排序】
Gym Class Time Limit: 6000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- 2016"百度之星" - 初赛(Astar Round2A)HDU 5695 拓扑排序+优先队列
Gym Class Time Limit: 6000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU - 5695 Gym Class (优先队列+拓扑排序)
题意:有N个人,每个人的ID为1~N,部分同学A不希望部分同学B排在他之前,排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数.在满足这个前提的情况下,将N个人排 ...
- HDU 4857 逃生 (反向拓扑排序 & 容器实现)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others) Mem ...
- ACM: HDU 1285 确定比赛名次 - 拓扑排序
HDU 1285 确定比赛名次 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u De ...
- ACM: hdu 2647 Reward -拓扑排序
hdu 2647 Reward Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Des ...
随机推荐
- java集合系列——Set之HashSet和TreeSet介绍(十)
一.Set的简介 Set是一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素.对 e1 和 e2,并且最多包含一个为 null 的元素. S ...
- mybatis typehandler
建立TypeHandler 我们知道java有java的数据类型,数据库有数据库的数据类型,那么我们在往数据库中插入数据的时候是如何把java类型当做数据库类型插入数据库,在从数据库读取数据的时候又是 ...
- #翻译#原文来自Database.System.Concepts(6th.Edition.2010)2.6Relational Operations,原文作者Abraham Silberschaz , Henry F. Korth , S. Sudarshan
2.6关系操作 所有的过程关系查询语言都提供一组操作,这些操作可以应用于单个关系或一对关系.这些操作具有良好的和期望的属性,它们的结果总是一个单一的关系.这个属性允许一个以模块化的方式组合其中的几个操 ...
- Elixir游戏服设计四
上章说到我们要引入syn https://github.com/ostinelli/syn/ 看过文档,它并没有直接提供{via, Module, Name} 相关的方法.我们需要封装一下. Name ...
- 使用路由延迟加载 Angular 模块
使用路由延迟加载 Angular 模块 Angular 非常模块化,模块化的一个非常有用的特性就是模块作为延迟加载点.延迟加载意味着可以在后台加载一个模块和其包含的所有组件等资源.这样 Angular ...
- Python自学笔记-生成器(来自廖雪峰的官网Python3)
感觉廖雪峰的官网http://www.liaoxuefeng.com/里面的教程不错,所以学习一下,把需要复习的摘抄一下. 以下内容主要为了自己复习用,详细内容请登录廖雪峰的官网查看. 生成器 通过列 ...
- 在ubuntu16.04中一键创建LAMP环境
步骤 1 执行命令apt-get update. 步骤 2 执行命令apt-get install lamp-server^. 步骤 3 在安装过程中会跳出Mysql数据库root用户密码设置窗口,按 ...
- sql 时间格式
在SQL Server数据库中,SQL Server日期时间格式转换字符串可以改变SQL Server日期和时间的格式,是每个SQL数据库用户都应该掌握的.本文我们主要就介绍一下SQL Server日 ...
- c#中字节数组byte[]、图片image、流stream,字符串string、内存流MemoryStream、文件file,之间的转换
字节数组byte[]与图片image之间的转化 字节数组转换成图片 public static Image byte2img(byte[] buffer) { MemoryStream ms = ne ...
- UEFI启动视频详解:启动分析+N项操作实例
============================================================= ※※※※最给力的视频解说※※※※ 2011hiboy全部共享资料:立刻去 ...