POJ - 3249 Test for Job (在DAG图利用拓扑排序中求最长路)
时间:2019-08-27
本文章向大家介绍POJ - 3249 Test for Job (在DAG图利用拓扑排序中求最长路),主要包括POJ - 3249 Test for Job (在DAG图利用拓扑排序中求最长路)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意
给出一个有n个结点,m条边的DAG图,每个点都有权值,每条路径(注意不是边)的权值为其经过的结点的权值之和,每条路径总是从入度为0的点开始,直至出度为0的点,问所有路径中权值最大者为多少,如下图,加粗的为权值最大者:
解题思路
这是在一个无起点、终点的图中的求最长路的问题,因此无法像一般的最长路问题那样求解。
首先,因为图中只存在点权,为了方便,我们一般将点权转化为边权:取每条边的权值为其终点的权值,将点权转化为边权。
然后,由于我们每条路径都是以入度为0的点开始,以出度为0的点结束,而且是求最大路,我第一想法就是AOV网中求事件的最晚完成时间,这两者是很相似的,不同的在于AOV网中有一个入度为0的源点和一个出度为0的汇点,而这个地方有多个入度为0的点和多个出度为0的点,不过实际的操作是完全一致的,都是利用拓扑排序的效果求最长路
为了方便理解,可以假设存在一个权值为0的点s向所有入度为0的点建边,然后把这个点当作起点,利用求拓扑序的时候,可以求出事件的最晚完成时间的效果,求其余各点到这个点的最长路,最后求出所有出度为0的点到s的最长路中的最大者,即为答案
代码区
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const ll inf = 1e18+10; const ll mod = 1e9 + 7; const int Max = 1e6 + 10; const int Max2 = 3e2 + 10; struct Edge { int to,next; ll dis; }edge[Max<<1]; int n, m; ll val[Max]; int head[Max],tot; int topo[Max],id; //记录每个点的拓扑序 int d_in[Max],d_out[Max]; //记录每个点的入度和出度 ll dist[Max]; //距离源点的最大距离 int init() { memset(head,-1,sizeof(head)); tot = 0; memset(topo,0,sizeof(topo)); id = 0; memset(d_in,0,sizeof(d_in)); memset(d_out,0,sizeof(d_out)); } void add(int u,int v,ll dis) { edge[tot].to = v; edge[tot].dis = dis; edge[tot].next = head[u]; head[u] = tot++; } void topoSort() { queue<int>q; //存储入度为0的点 for(int i = 1;i <= n ;i ++) { if(d_in[i] == 0) { q.push(i); dist[i] = val[i]; //初始化 } } while(!q.empty()) { int u = q.front();q.pop(); topo[u] = ++id; for(int i = head[u] ; i != -1 ; i = edge[i].next) { int v = edge[i].to; ll dis = edge[i].dis; if(!topo[v]) { d_in[v] --; dist[v] = max(dist[v],dist[u] + dis); if(d_in[v] == 0) q.push(v); } } } } int main() { #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i = 1;i <= n ;i ++) scanf("%lld",val+i); for(int i = 1, u, v ; i <= m ;i ++) { dist[i] = -inf; scanf("%d%d",&u,&v); d_out[u] ++; d_in[v]++; add(u,v,val[v]); //以终点的权值作为边的权值 } topoSort(); ll max_dis = -inf; for(int i = 1;i <= n ;i ++) { if(d_out[i] == 0) //只对出度为0的点进行判断 { max_dis = max(max_dis,dist[i]); } } printf("%lld\n",max_dis); } return 0; }
原文地址:https://www.cnblogs.com/winter-bamboo/p/11419268.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【回溯算法】N叉树相关技巧
- 【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练
- 数据结构练手小项目(AVL树、哈希表、循环链表、MySQL数据库)
- 【LeetCode】每日一题(8.2)二叉树展开为链表
- 【小技巧】argc和argv的用法
- 全面分析redis持久化机制
- 【奇技淫巧】-- 接雨水
- 【奇技淫巧】-- 最长连续序列
- 【redis】跟我一起动手玩玩redis主从复制和哨兵模式
- 【C++】八大排序算法 :GIF + 亲测代码 +专项练习平台
- 【C++】勉强能看的线程池详解
- 国密SSL协议之Java编程
- 7. Jackson用树模型处理JSON是必备技能,不信你看
- epoll,求知者离我近点
- SOCKET网络编程 (通俗易懂入门篇)