[POJ3249]Test for Job [拓扑排序+DAG上的最长路径]

给定一张带点权的DAG 求一条入度为0节点到出度为0节点的最长路

把点权转化为边权(同时多源转化成单源):边u->v的权值为W[v],这样入度为0的节点权值会被遗漏,新开一个点0向入度为0的点u连有向边,权值为W[u],这样就只有0是入度为0的点了。

先进行拓扑排序,再利用DAG拓扑排序后的特性求出最长路径

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <cstdio>
 6 using namespace std;
 7 typedef long long LL;
 8
 9 template<class T> void read(T & x){
10   register int c = getchar(), f = 1; x = 0;
11   while(!isdigit(c)){if (c == ‘-‘) f = -1; c = getchar();}
12   while(isdigit(c)) x = x*10+(c&15), c = getchar();
13   x *= f;
14 }
15 const int N = 100005;
16 struct Edge{int v, w, next;}G[N*20];
17 int n, m, s, head[N], tot,  ind[N], out[N], W[N]; LL dis[N], ans = -123023423423;
18 void toposort(int s) {
19   int topo[N], cnt = 0;
20   topo[++cnt] = 0;
21   for(int k = 0; k <= cnt; ++k)
22     for(int i = head[topo[k]]; i; i = G[i].next) {
23       int v = G[i].v;
24       ind[v]--;
25       if (ind[v]==0) topo[++cnt] = v;
26     }
27   memset(dis,0xc0,sizeof(dis));dis[s] = 0;
28   for(int k = 0; k <= cnt; ++k)
29     for(int i = head[topo[k]]; i; i = G[i].next) {
30       int v = G[i].v, w = G[i].w;
31       dis[v] = max(dis[topo[k]]+w, dis[v]);
32     }
33 }
34
35 inline void add(int u, int v, int w) {
36   G[++tot].v=v, G[tot].w=w, G[tot].next=head[u];head[u]=tot;
37   ind[v]++, out[u]++;
38 }
39
40 int main(void){
41   while(scanf("%d%d", &n, &m) == 2){
42     memset(head,0,sizeof(head));tot=0;memset(ind,0,sizeof(ind));memset(out,0,sizeof(out));
43     ans = 0xc0c0c0c0c0c0c0c0;
44     for(int i = 1; i <= n; ++i) read(W[i]);
45     for(int u, v, i = 1; i <= m; ++i) {
46       read(u), read(v);
47       add(u, v, W[v]);
48     }
49     for(int i = 1; i <= n; ++i) {
50       if (!ind[i]) add(0,i,W[i]);
51     }
52     toposort(s);
53     for(int i = 1; i <= n; ++i) {
54       if (!out[i]) ans = max(ans, dis[i]);
55     }
56     cout << ans << ‘\n‘;
57   }
58   return 0;
59 }

原文地址:https://www.cnblogs.com/Ycrpro/p/8550884.html

时间: 2024-10-09 19:55:36

[POJ3249]Test for Job [拓扑排序+DAG上的最长路径]的相关文章

POJ 3114 - Countries in War(强连通分量+缩点+拓扑排序+DAG最短路)

Countries in War Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Appoint description: Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The impor

poj3249 Test for Job --- 拓扑排序

从起点开始,按照拓扑排序的顺序依次更新dp[i],表示到该点能获得的最大值 #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map>

uva103(最长递增序列,dag上的最长路)

题目的意思是给定k个盒子,每个盒子的维度有n dimension 问最多有多少个盒子能够依次嵌套 但是这个嵌套的规则有点特殊,两个盒子,D = (d1,d2,...dn) ,E = (e1,e2...en) 只要盒子D的任意全排列,小于盒子E,那么就说明 盒子D能放入盒子E中,其实就是将两个盒子的维度排序,如果前一个盒子的维度依次小于后一个盒子,那么就说明前一个盒子能放入后一个盒子中 这个题目能够转化为最长递增子序列. 首先将盒子的维度从小到大排序,然后将k个盒子,按照排序后的第一维度从小到大排

NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)

本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽. 本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这道题是很经典的DAG上的最长路问题,用dp[ i ]表示以i为出发点的最长路的长度,因为每一步都只能走向他的相邻点,则 d[ i ]  = max(d[ j ] + 1)这里 j 是任意一个面积比 i 小的举行的编号. 下面的代码中附带了最小字典序最长路打印的问题,我们找到第一个路径最长的 i,往后

POJ3249 Test for Job(拓扑排序+dp)

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10137   Accepted: 2348 Description Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, It's hard to have a jo

hdu 1224(动态规划 DAG上的最长路)

Free DIY Tour Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5815    Accepted Submission(s): 1855 Problem Description Weiwei is a software engineer of ShiningSoft. He has just excellently fulfi

POJ 1949 Chores(DAG上的最长路 , DP)

题意: 给定n项任务, 每项任务的完成用时t和完成每项任务前需要的k项任务, 求把所有任务完成的最短时间,有当前时间多项任务都可完成, 那么可以同时进行. 分析: 这题关键就是每项任务都会有先决条件, 要完成该项任务a必须先完成他的先决条件. 所以对于每个先决条件, 我们构建一条有向边到任务本身, 然后因为要求一个最小值, 按照最长路的方式松弛(dis[v] >= dis[u] + d, u是v的先决条件, d是v的完成时间,我们以边的终点完成时间作为边的权), 遇到没有出度的边记录答案. 方法

XMU 1040 Schedule 【拓扑排序】

1040: Schedule Time Limit: 500 MS  Memory Limit: 64 MBSubmit: 12  Solved: 2[Submit][Status][Web Board] Description Resently, loneknight is doing research on job shop schedule problem(JSP for short). Let us take a look at JSP, there are n jobs and m m

DAG上动态规划

很多动态规划问题都可以转化为DAG上的最长路,最短路,或路径计数问题. 硬币问题: 有N中硬币,面值分别为v1,v2,v3,……vn,每种都无穷多,给定非负整数S,可以选用多少个硬币,使他们的总和恰好为S.输出硬币数目的最小值和最大值. 解:每种面值看作一个点,表示:还需要凑足的面值.则开始状态为S,目标状态为0:若当前状态为i,当使用硬币j后,状态转为i-v[j]. 代码说明好了. 1 #include <iostream> 2 #include <cstdio> 3 #incl