poj 3249 Test for Job 最长路
来源:互联网 发布:旅游市场需求状况数据 编辑:程序博客网 时间:2024/06/15 08:01
题意:给出一个有向无环图(DAG),可以不强连通,每个点有点权(正负)。
现在有从每个入度为0的点到它可达的出度为0的点的所有路径,求每条路径上所有点权之和的最大值。
分析:其实就是求一条最长路。
做法:
- 很容易想到将spfa的松弛过程改为更新最大值
- 记忆化搜索,取当前节点所有后继的最大值更新自己
- 拓扑排序,然后dp递推过去,是2的逆过程
分享:分享三份代码,与大家共同学习。
法1:反向建图,spfa变形。复杂度O(kE),k是一个不知道多大的常数(据说平均是2)。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;#define rep(i,n) for(int i=0;i<n;i++)#define rep1(i,n) for(int i=1;i<=n;i++)#define LL long long#define N 100001 //顶点数#define M 1000001 //边数//poj3249 DAG 最长路?const LL INF = 1LL<<60;struct edge { int y, next;};int V, E; //顶点数,边数LL d[N]; //最长距离int q[M], head, tail; //队列,头,尾int done[N]; //是否在队列里edge e[M]; //E条边int next[N], el; //i的下一条边的位置,记录边数int val[N]; //节点值int cnti[N]; //是否有入度void add(int x, int y) { //加边 e[++el].y = y; e[el].next = next[x]; next[x] = el;}void spfa() { head = tail = 0; rep1(i,V) d[i] = -INF, done[i] = 0, q[i] = 0; rep1(s,V) if(cnti[s]==0) { d[s] = val[s]; done[s] = 1; q[tail++] = s; } while(head < tail) { int x = q[head++]; done[x] = 0; for(int i=next[x]; i; i=e[i].next) { int y = e[i].y; LL tmp = d[x]+(LL)val[y]; if(d[y] < tmp) { //松弛操作 d[y] = tmp; if(!done[y]) { //不在队列,入队 q[tail++] = y; done[y] = 1; } } } }}int main() { while(scanf("%d%d", &V,&E) != EOF) { el = 0; rep1(i,V) next[i] = cnti[i] = 0; rep1(i,V) scanf("%d", val+i); for(int i=0, x,y; i<E; i++) { scanf("%d%d", &x,&y); add(y,x); //反向建图 cnti[x]=1; } spfa(); LL ans = -INF; rep1(i,V) { if(next[i]==0 && ans < d[i]) { ans = d[i]; } } printf("%I64d\n", ans); } return 0;}
法2:dfs记搜,复杂度O(V+E)
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;#define rep(i,n) for(int i=0;i<n;i++)#define rep1(i,n) for(int i=1;i<=n;i++)#define LL long long#define N 100001 //顶点数#define M 1000001 //边数//poj3249 DAG dfsconst LL INF = 1LL<<60;struct edge{ int y, next;};int V, E; //顶点数,边数LL d[N]; //最长距离edge e[M]; //E条边int next[N], el; //i的下一条边的位置,记录边数int val[N]; //节点值int cnti[N], cnto[N]; //入度,出度inline void add(int x, int y) { //加边 e[++el].y = y; e[el].next = next[x]; next[x] = el;}LL dfs(int v) { if(d[v]!=-INF) return d[v]; if(cnto[v]==0) return d[v] = val[v]; for(int i=next[v]; i; i=e[i].next) { d[v] = max(d[v], (LL)val[v]+dfs(e[i].y)); } return d[v];}int main() { while(scanf("%d%d", &V,&E) != EOF) { el = 0; rep1(i,V) next[i] = cnti[i] = cnto[i] = 0; rep1(i,V) scanf("%d", val+i); for(int i=0, x,y; i<E; i++) { scanf("%d%d", &x,&y); add(x,y); cnti[y]++; cnto[x]++; } LL ans = -INF; rep1(i,V) d[i] = -INF; rep1(i,V) { if(cnti[i]==0) { ans = max(ans, dfs(i)); } } printf("%I64d\n", ans); } return 0;}
法3:拓扑排序+dp,复杂度O(V+E)
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;#define rep1(i,n) for(int i=1;i<=n;i++)#define LL long long#define N 100001 //顶点数#define M 1000001 //边数//poj3249 spfa + dpconst LL INF = 1000000000000000; //1e15struct edge { int y, next;};int V, E; //顶点数,边数LL d[N]; //最短距离int q[M], head, tail; //队列,头,尾(切记:手写数组必须开到 > M)edge e[M]; //E条边int next[N], el; //i的下一条边的位置,记录边数int val[N]; //节点权值int ind[N], outd[N]; //入度,出度void init() { el = 0; rep1(i,V) next[i] = ind[i] = outd[i] = 0; rep1(i,V) d[i] = -INF;}inline void add(int x, int y) { //加边 e[++el].y = y; e[el].next = next[x]; next[x] = el;}void tpo() { //拓扑排序 head = tail = 0; rep1(i,V) if(ind[i]==0) { d[i] = val[i]; q[tail++] = i; } while(head < tail) { int x = q[head++]; for(int i=next[x]; i; i=e[i].next) { int y = e[i].y; d[y] = max(d[y], d[x]+val[y]); ind[y]--; if(ind[y]==0) q[tail++] = y; } }}int main() { while(scanf("%d%d", &V,&E) != EOF) { init(); rep1(i,V) scanf("%d", val+i); for(int i=0, x,y; i<E; i++) { scanf("%d%d", &x,&y); add(x,y); ind[y]++; outd[x]++; } tpo(); LL ans = -INF; rep1(i,V) if(outd[i]==0) ans = max(ans, d[i]); printf("%I64d\n", ans); } return 0;}
- poj 3249 Test for Job 最长路
- POJ 3249 Test for a job dp最长路
- poj 3249 Test for Job (DAG最长路 记忆化搜索解决)
- POJ 3249 Test For Job
- POJ 3249 Test for Job
- poj 3249 Test for Job
- POJ 3249 Test for Job
- POJ 3249 Test for Job
- poj 3249 Test for Job
- POJ 3249 Test for Job
- poj 3249 Test for Job (DP)
- poj 3249 Test for Job (拓扑排序)
- POJ 3249 Test for Job【SPFA】
- poj--3249 Test for Job(topsort + dp)
- HDU 3249 Test for job (有向无环图上的最长路,DP)
- POJ 3249 Test for Job(拓扑排序)
- poj 3249 Test for Job(拓扑排序+DP)
- POJ 3249 Test for Job(记忆化搜索)
- 交换机的几种配置方法
- 这是一个为了学习C语言而开通的博客
- Android工程下assets文件夹与res文件夹的区别
- java的基本数据不能传引用带来的麻烦.
- MATLAB生成可执行文件
- poj 3249 Test for Job 最长路
- libev and libevent
- Project has no project.properties file! Edit the project properties to set one!
- 【分享】沪深300指数-历史数据
- java操作xml的四种方式
- 旋转矩阵(维基百科)
- 关于extjs checkboxgroup 数据修改时候数据匹配加载
- 运行其它程序方法
- jQuery 语法,以及文件就绪函数