拓扑排序·一

分析:

此题就是求一个有向图中是否存在环。 如存在环则输出"Wrong", 若不存在环, 说明课程安排的合理,输出"Correct"。

题中的提示说的已经十分清楚了。

总的来说就是

① 找出入度为0的点(说明该点没有前驱),把该点放入集合T中。 把所有从该点出发的边都删除;

② 遍历剩余的点, 找出入度为0 的点, 重复①操作。

③直到不存在入度为0的点。 结束。如果此时集合T中包含所有的点, 那么该图不存在环, 否则存在环。

注意:1、执行操作①时, 在删除边时(u, v),同时更新与其相关点的入度(du[v]--);

2、 在执行操作②时, 需要遍历所有点, 点少的时候可行, 点多的话很容易超时。 所以题目的提示中告诉了一个好办法就是: 执行操作①更新相关点的入度时直接判断一下是否为0, 若为零则入队列。 这样会省很多时间。

如下图例子:

开始点1入度为0, 点1加入集合T,   删除从1出发的边;  更新相关点的入度, 点2、3的入度都变为0了 , 2、3入队列;

再依次对点2、3进行①操作, 2、3加入T,   删除边(2, 4), (3, 4), 此时没有其他点入度为0了, 结束操作, T中未包含所有点, 说明该图中有环;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std; int t, n, m, sum, du[];
vector<int> vec[]; int ac()
{
queue<int> q;
for(int i = ; i <= n; i++)//遍历一边所有点, 把入度为0的点,全加入队列q中
{
if(du[i] == )
q.push(i);
}
while(!q.empty())
{
int tem = q.front();//在队列中取出一个入度为0的点
q.pop();
sum++;
//把所有从tem出发的边(tem, v)删除并更新du[],
for(int i = ; i < vec[tem].size(); i++)
{
du[vec[tem][i]]--;
if(du[vec[tem][i]] == )//若点vec[tem][i]入度更新后为0, 则入队列
q.push(vec[tem][i]);
}
vec[tem].clear();
}
if(sum == n) return ;
else
return ;
}
int main()
{
cin >> t;
while(t--)
{
scanf("%d%d", &n, &m);
//用vec[]来存边
for(int i = ; i <= n; i++) vec[i].clear();
memset(du, , sizeof(du));//初始化入度, 置为0;
for(int i = ; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
vec[x].push_back(y); // 加入边
du[y]++; //记录入度
}
sum = ;
int ans = ac();
if(ans == )
printf("Correct\n");
else
printf("Wrong\n");
}
return ;
}

拓扑排序·二

分析:

和上一道差不多, 只是多了一项就是记录每个点的病毒数。  每个点的病毒数 = 自身病毒数 +  所有能够达到它的节点病毒数之和( 就是所有它前驱点的病毒数的和)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int mod = ;
int n, m, k, sum, virus[], du[];
vector<int> vec[]; void ac()
{
queue<int> q;
for(int i = ; i <= n; i++)
{
if(du[i] == )
q.push(i);
}
while(!q.empty())
{
int tmp = q.front(); q.pop();
sum = (sum + virus[tmp]) % mod; //把所有前驱点为 tmp 的点的病毒数都加上 tmp的病毒数
for(int i = ; i < vec[tmp].size(); i++)
{
int b = vec[tmp][i];
virus[b] = (virus[tmp] + virus[b]) % mod;// 此处也一定要取模,
du[b]--;
if(du[b] == )
q.push(b);
}
vec[tmp].clear();
}
}
int main()
{
while(scanf("%d%d%d", &n, &m, &k) != EOF)
{
memset(virus, , sizeof(virus));
memset(du, , sizeof(du));
for(int i = ; i <= n; i++) vec[i].clear(); for(int i = ; i <= k; i++)
{
int x;
scanf("%d", &x);
virus[x]++;
}
for(int i = ; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
vec[x].push_back(y);
du[y]++;
} sum = ;
ac();
printf("%d\n", sum);
}
return ;
}

hiho拓扑排序专题 ——第四十八、四十七周的更多相关文章

  1. Unity 游戏框架搭建 2019 (四十八/四十九) MonoBehaviourSimplify 中的消息策略完善&关于发送事件的简单封装

    MonoBehaviourSimplify 中的消息策略完善 在上一篇,笔者说,MonoBehaviourSimplify 中的消息策略还有一些小问题.我们在这篇试着解决一下. 先贴出来代码: usi ...

  2. NeHe OpenGL教程 第四十八课:轨迹球

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. SQL注入之Sqli-labs系列第四十七关,第四十八关,第四十九关(ORDER BY注入)

    0x1 源码区别点 将id变为字符型:$sql = "SELECT * FROM users ORDER BY '$id'"; 0x2实例测试 (1)and rand相结合的方式 ...

  4. 《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)

    1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...

  5. 第四十八个知识点:TPM的目的和使用方法

    第四十八个知识点:TPM的目的和使用方法 在检查TPM目的之前,值得去尝试理解TPM设计出来的目的是为了克服什么样的问题.真正的问题是信任.信任什么?首先内存和软件运行在电脑上.这些东西能直接的通过操 ...

  6. hiho一下 第四十八周 拓扑排序·二【拓扑排序的应用 + 静态数组 + 拓扑排序算法的时间优化】

    题目1 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当 ...

  7. [hihoCoder] 第四十八周: 拓扑排序·二

    题目1 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当 ...

  8. abp(net core)+easyui+efcore实现仓储管理系统——入库管理之十二(四十八)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  9. SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关

    0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...

随机推荐

  1. python dict{}和set([])

    200 ? "200px" : this.width)!important;} --> 介绍 dict(dictionary),在其他语言中也称为map,使用键-值(key- ...

  2. ecshop收货人信息中修改手机号为必填

    Ecshop 修改收货人信息 把电话改成选择填写 手机改为必填 (加强版) 1.  编辑根目录/js/utils.js 增加手机号码的正则表达式 参照Utils.isTel = function ( ...

  3. C# 解压zip压缩文件

    此方法需要在程序内引用ICSharpCode.SharpZipLib.dll 类库 /// <summary> /// 功能:解压zip格式的文件. /// </summary> ...

  4. Linux单词表

     su:Swith user  切换用户,切换到root用户cat: Concatenate  串联uname: Unix name  系统名称df: Disk free  空余硬盘du: Disk  ...

  5. 【M8】了解各种不同意义的new和delete

    1.首先考虑new operator,new operator 可以认为做了三件事情:a.调用operator new分配一块内存:b.在这块内存上调用构造方法构造对象:返回指针. 2.operato ...

  6. utf-8 和gbk编码的差别

    UTF- 8: 是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码. GBK 是国家标准GB2312基础上扩容后兼容GB2312的标准. GBK的文 ...

  7. 【Bootstrap3.0建站笔记三】AspNetPager分页,每一列都可排序

    1.AspNetPager分页,实现每一列都可排序:           (1).须要将默认排序字段放在HTML页面中.           (2).排序字段放置为td节点的属性. 如图: 实现的效果 ...

  8. [IOS]自定义长触屏事件

    写一个Demo来自定义一个长触屏事件,自定义长按手势. 实现步骤: 1.创建一个自定义手势类,命名为LongPressGestureRecognizer,在创建的时候继承UIGestureRecogn ...

  9. [Javascript] Monads

    Monads allow you to nest computations. They are a pointed functor that adds mjoin and chain function ...

  10. iOS常用的存储方式介绍

    在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用的存储工具/方式: NSU ...