最近研究了几道图论的题目,都是图论入门的算法,用的比较多的就是拓扑排序,多用于有着先后顺序的题目,也可以用来判断环,做个小总结。

杂物

题目链接:杂务 - 洛谷

这一题需要计算最短的时间,利用了记忆化搜索的方式。将每一项工作抽象为图中的节点,所有前面需要完成的也就是节点的前驱,因为每一项工作完成所需要的最短总时长其实就是完成前面需要的工作的最早时长再加上这个工作的时长,因为所有工作的最早完成时间在一开始是未知的,所以需要先把所有前驱给计算出来, 所以搜索是需要先更新前驱结点,如果计算过了就直接返回结果,本质上也是拓扑排序,利用转移方程finalT[i]=min(finalT[...])+t[i],也就是当前工作的时长加上最早前驱计算每个节点,确定最终答案。

#include<stdio.h>
#include<algorithm>
#include<vector>
#define Max 100100
using namespace std;
vector<int>v1[Max];
int t[Max];//每个点的时间
int flag[Max];//标记每个点的访问情况
int finalT[Max];//标记最终的答案
int n;int dfs(int x)
{if (flag[x])return finalT[x];for (int i = 0; i < v1[x].size(); i++)finalT[x] = max(finalT[x], finalT[v1[x][i]] + t[x]);flag[x] = 1;return finalT[x];
}int main()
{scanf("%d", &n);int x, y;for (int i = 1; i <= n; i++){scanf("%d%d", &x, t + i);while ( scanf("%d",&y) && y)//这样写更简洁{v1[x].push_back(y);//这个方笛一定要注意,给的形式是前驱}}int ans = 0;for (int i = 1; i <= n; i++)finalT[i] = t[i];for (int i = 1; i <= n; i++)ans = max(ans, dfs(i));printf("%d\n", ans);return 0;
}

最大食物链计数

题目链接:最大食物链计数 - 洛谷

这一题需要计算食物链的总数,将每个生物抽象为图中节点,一个生物吃另一个生物就是作为前驱。那么只有一个节点只有入度而没有出度才可以算作一条完整的食物链,对于每个节点,到达这个节点所有的食物链总数其实就是所有指向这个节点的食物链总和,也就是num[i]=∑num[j],j是i的前驱, 初始状态是将每个只有出度的点作为1,最后求和是对所有没有出度的求和。

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define mod 80112002
vector<int>v[10000];
int n,m;
int flag[10000];
int vis[10000];//标记这个点有没有出度int cal(int x)
{if (flag[x])return flag[x];if (v[x].size() == 0)return flag[x] = 1;//没有前驱就是1for (int i = 0; i < v[x].size(); i++){flag[x] = (flag[x] + cal(v[x][i])) % mod;}return flag[x];
}int main()
{scanf("%d%d", &n, &m);int x, y;for (int i = 1; i <= m; i++){scanf("%d%d", &x, &y);vis[x] = 1;v[y].push_back(x);}int ans = 0;for (int i = 1; i <= n; i++){if(!vis[i])ans = (ans + cal(i)) % mod;//cal计算所有前驱的和}printf("%d\n", ans);return 0;
}

排序

题目链接:排序 - 洛谷

这道题因为有三种情况,也就是矛盾---出现环,无法排序---没有唯一拓扑序列,排序完成--有唯一的拓扑序列,恰好考察了拓扑排序的应用。这一题读入点要标记出现的点,在排序时候只要出现的点都有了那么排序就完成了,但是在排序中会出现几种情况:第一种是找了一轮都找不到度为0的点,那么这时候是出现矛盾了;第二种要是找了一轮找到了好几个度为0的那么就无法确定,一开始我是吃了这里的亏,也就是在函数中出现无法确定直接返回,但是由于无法确定还可能最终是矛盾的,所以不可以直接返回,最终返回是矛盾优先,因为直接就不用后面的判断了;第三种就是排序完成了,出现的字母个数也是等于总个数,那么就可以退出了。

#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
vector<int>v[200];
int du[200],du2[200];
char res[30];
bool exist[200];
bool flag[200];
queue<int>q;
int n, m;int topo_sort(int cag)
{int cnt = 0;int not_sure = 0;for (int i = 'A'; i <= 'Z'; i++){int first = 0;//标记是不是只有一个入队if (exist[i] && du2[i] == 0){if (!first)first = 1;else not_sure = 1;q.push(i);res[++cnt] = i;}}if (q.empty())return -1;//矛盾while (!q.empty()){int x = q.front();q.pop();int first = 0;for (int i = 0; i < v[x].size(); i++){du2[v[x][i]]--;if (!du2[v[x][i]]){if (!first)first = 1;else not_sure = 1;q.push(v[x][i]);res[++cnt] = v[x][i];}}}//printf("cnt=%d,cag=%d\n", cnt,cag);if (cnt != cag)return -1;//如果没排序完,那么就是有环,也就是矛盾if (not_sure)return 0;//不确定return 1;//排序完毕
}int main()
{scanf("%d%d", &n, &m);char x, y;int cag = 0;//当前有的种类for (int i = 1; i <= m; i++){scanf(" %c<%c", &x, &y);cag += (1-exist[x] + 1-exist[y]);exist[x] = 1;exist[y] = 1;//printf("%c:%c\n", x, y);v[x].push_back(y);du[y]++;for (int j = 'A'; j <= 'Z'; j++)du2[j] = du[j];int ans = topo_sort(cag);//printf("%d %d\n", i, ans);if (ans == -1)//矛盾{printf("Inconsistency found after %d relations.\n", i);return 0;}else if (cag==n && ans == 1)//排序完了{printf("Sorted sequence determined after %d relations: ", i, res);for (int j = 1; j <= n; j++) printf("%c", res[j]);printf(".\n");return 0;}}printf("Sorted sequence cannot be determined.\n");return 0;
}

车站分级

题目链接:[NOIP2013 普及组] 车站分级 - 洛谷

这一题放在这里就是因为我觉得这一题就比较像是上一题排序的变形,从题目给出条件来看,车站经过的所有车站只要没有停,那么这个车站一定比停过的车站等级都要低,所以给出一个序列之后,比如1,3,设dj[i]为车站i的等级,那么就隐含了dj[1]>dj[2],dj[3]>dj[2],那么把所有的序列都转化为不等式,那么这一题就跟上一题一样了。需要注意的就是这一题需要统计的数量就是有多少层,每次找完一轮,度为0的都算作一层,相当于这些车站之间没有大小关系,但是跟不同层的是有前后关系的。

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define N 1001
bool flag[N][N];//标记这条边flag[x][y]x是否已经建立和y的关系
vector<int>v[N];
int n, m,ans;
bool vis[N];
int du[N];
int Min = 0x3f3f3f, Max = -0x3f3f3f;
int a[N];//存储车道序列和后面暂时存放度0的点
void topo()
{//要计算有多少层,每一次找完一轮有几个度为0,那么这一次找到的都是算作一层//先存储起来,然后逐个减度int all_num=Max-Min+1;//这一轮找到的个数和总个数while (all_num){int num = 0;//for (int i = Min; i <= Max; i++)//   printf("du[i]=%d\n", du[i]);for (int i = Min; i <= Max; i++){//printf("ans=%d\n", ans);if (!vis[i] && !du[i]){a[++num] = i;all_num--;vis[i] = 1;}}ans++;//一层//printf("all_num=%d\n", all_num);for (int i = 1; i <= num; i++){int x = a[i];for (int j = 0; j < v[x].size(); j++)du[v[x][j]]--;}}
}int main()
{scanf("%d%d", &n, &m);int t, x;for (int i = 1; i <= m; i++){scanf("%d", &t);for (int i = 1; i <= t; i++){scanf("%d", a+i);vis[a[i]] = 1;}//printf("t=%d\n", t);Min = min(Min, a[1]);Max = max(Max, a[t]);for (int i = a[1]; i <= a[t]; i++){if (!vis[i])//表示没有出现过,这个点要比所有出现过的点要小{//建边for (int j = 1; j <= t; j++){if (!flag[i][a[j]])//如果没有建过边{flag[i][a[j]] = 1;v[i].push_back(a[j]);du[a[j]]++;}}}}//一条车道建立完毕for (int i = a[1]; i <= a[t]; i++)vis[i] = 0;}//printf("%d %d\n", Min, Max);topo();printf("%d\n", ans);return 0;
}

就先写到这么多吧。

图论---拓扑排序的应用相关推荐

  1. 数据结构-图论-拓扑排序模板题(hdu3342)(poj1270)(hdu4857)

    dfs与bfs的很直接的应用就是拓扑排序. 拓扑排序如果用数组来模拟链表进行操作,既解决了稀疏图的空间问题,又解决了用链表进行操作麻烦的问题 但是拓扑排序并不是数字大小之间的排序,而是某些事情之间的顺 ...

  2. 图论--拓扑排序--模板

    //字典序号最小 #include <cstdio> #include <cstring> #define MAXN 517 int G[MAXN][MAXN]; //路径 i ...

  3. 图论--拓扑排序--HDU-1285确定比赛名次

    Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委 ...

  4. 图论--拓扑排序--判断是否为DAG图

    #include<cstdio> #include<cstring> #include<vector> #include<queue> using na ...

  5. 图论--拓扑排序--判断一个图能否被拓扑排序

    拓扑排序的实现条件,以及结合应用场景,我们都能得到拓扑排序适用于DAG图(Directed Acyclic Graph简称DAG)有向无环图, 根据关系我们能得到一个线性序列,实现的方式是DFS,具体 ...

  6. 2022.3.24 图论——拓扑排序算法

    文章目录 一.拓扑排序简介 二.例题 1.题目 2.分析 3.代码 一.拓扑排序简介 1.Topological Sorting,指的是一个DAG(Directed Acyclic Graph)即有向 ...

  7. 【算法练习】数据结构/图论 poj4084:拓扑排序

    题目链接:http://bailian.openjudge.cn/practice/4084 4084:拓扑排序 总时间限制: 1000ms 内存限制: 65536kB 描述 给出一个图的结构,输出其 ...

  8. Algorithm:C++语言实现之图论算法相关(图搜索广度优先BFS、深度优先DFS,最短路径SPF、带负权的最短路径Bellman-ford、拓扑排序)

    Algorithm:C++语言实现之图论算法相关(图搜索广度优先BFS.深度优先DFS,最短路径SPF.带负权的最短路径Bellman-ford.拓扑排序) 目录 一.图的搜索 1.BFS (Brea ...

  9. 图论入门(一),拓扑排序生成拓扑序列与Dijkstra求最短路

    基本知识 Dijkstra基本思想 拓扑排序思维视频讲解 848:有向图的拓扑排序 题目链接 题解: #include<bits/stdc++.h> using namespace std ...

最新文章

  1. [Django]APP级别的静态文件处理
  2. NLineInputFormat案例
  3. html认识数字游戏大全,认识数字小游戏,就是这么简单!为孩子收藏
  4. 机器学习将在游戏开发中的6种应用
  5. 混合代码块 Markdown Leedcde
  6. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 6丨寻找用户推荐人【难度简单】
  7. 计算机类自主招生推荐信,自主招生推荐信范文:中国人民大学自主招生推荐信...
  8. TomTom导航新增IFTTT功能 可连接到车主日常生活设备
  9. 双向链表list.h升序排序
  10. 一次有趣的面试经历,当前端面试碰到后端面试官会发生什么?
  11. 2020 CTF暑假夏令营培训Day1 安全杂项Misc
  12. 软件工程第二版(判断题答案)
  13. java web对cpu要求_java web服务器cpu占用过高 (转载)
  14. 运行在网络处理器上的嵌入式Linux系统
  15. 书摘—20几岁不学应酬,30几岁只能发愁
  16. 为什么大学生活这么充实(累)
  17. 华为RH2288V3安装CentOS、Ubuntu、Windows 2012
  18. grads右侧的色标图注画的命令
  19. SQL Server Arithmetic overflow error converting nvarchar to data type numeric
  20. 【计算机网络:自顶向下方法】期末复习总结(USTC 2020秋 zq班)

热门文章

  1. 毫无基础的人如何入门Python这个编程语言?
  2. Unsupervised domain adaptation for cross-modality liver segmentation via joint adversarial learning
  3. 鸿蒙os 2.0 beta 3,华为发布鸿蒙OS2.0手机开发者Beta3版本
  4. python functools_Python——functools
  5. matlab 背景差分法,背景差分法MATLAB实现
  6. 当你看到这你已经赢麻了,2022软件测试八股文最全文档,有它直接大杀四方
  7. Patroni-2.0.0(Postgresql集群高可用方案)说明书
  8. 分享|38款测序仪性能指标统计
  9. Android slider加载网络图片的框架
  10. 研究fastdds v2.8.0 2之 Domain 模块 4