POJ3249 Test for Job 【DAG】+【记忆化搜索】

Test for Job

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 9201   Accepted: 2080

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 job, since there are swelling numbers of the unemployed. So some companies often use hard tests for their recruitment.

The test is like this: starting from a source-city, you may pass through some directed roads to reach another city. Each time you reach a city, you can earn some profit or pay some fee, Let this process continue until you reach a target-city. The boss will
compute the expense you spent for your trip and the profit you have just obtained. Finally, he will decide whether you can be hired.

In order to get the job, Mr.Dog managed to obtain the knowledge of the net profit Vi of all cities he may reach (a negative Vi indicates that money is spent rather than gained) and the connection between cities. A
city with no roads leading to it is a source-city and a city with no roads leading to other cities is a target-city. The mission of Mr.Dog is to start from a source-city and choose a route leading to a target-city through which he can get the maximum profit.

Input

The input file includes several test cases.

The first line of each test case contains 2 integers n and m(1 ≤ n ≤ 100000, 0 ≤ m ≤ 1000000) indicating the number of cities and roads.

The next n lines each contain a single integer. The ith line describes the net profit of the city iVi (0 ≤ |Vi| ≤ 20000)

The next m lines each contain two integers xy indicating that there is a road leads from city x to city y. It is guaranteed that each road appears exactly once, and there is no way to return to a previous city.

Output

The output file contains one line for each test cases, in which contains an integer indicating the maximum profit Dog is able to obtain (or the minimum expenditure to spend)

Sample Input

6 5
1
2
2
3
3
4
1 2
1 3
2 4
3 4
5 6

Sample Output

7

Hint

Source

POJ Monthly--2007.07.08, 落叶飞雪

题意:求某一原点到终点的最大点权和。

DAG:

#include <stdio.h>
#include <string.h>
#define inf 0x7fffffff
#define maxn 100002
#define maxm 1000002

int id, cost[maxn], sta[maxn];
struct Node2{
    int v, first;
} head[maxn];
struct Node{
    int to, next;
} E[maxm];
bool vis[maxn], in[maxn], out[maxn];

void addEdge(int u, int v)
{
    E[id].to = v; E[id].next = head[u].first;
    head[u].first = id++;
}

void getMap(int n, int m)
{
    int i, u, v;
    for(i = 1; i <= n; ++i){
        scanf("%d", &head[i].v);
        head[i].v = -head[i].v; in[i] = 0;
        head[i].first = -1; out[i] = 0;
        vis[i] = 0; cost[i] = inf;
    }
    for(i = id = 0; i < m; ++i){
        scanf("%d%d", &u, &v); out[v] = 1;
        addEdge(v, u); in[u] = 1;
    }
}

void DAG(int n)
{
    int i, u, v, id2 = 0, ans = inf, tmp;
    for(i = 1; i <= n; ++i)
        if(!in[i]){
            sta[id2++] = i; vis[i] = 1;
            cost[i] = head[i].v;
            if(!out[i] && cost[i] < ans) ans = cost[i];
        }
    while(id2){
        u = sta[--id2]; vis[u] = 0;
        for(i = head[u].first; i != -1; i = E[i].next){
            v = E[i].to; tmp = cost[u] + head[v].v;
            if(tmp < cost[v]){
                cost[v] = tmp;
                if(!vis[v]){
                    vis[v] = 1; sta[id2++] = v;
                }
                if(!out[v] && tmp < ans) ans = tmp;
            }
        }
    }
    //if(ans < 0) ans = - ans;
    printf("%d\n", -ans);
}

int main()
{
    int n, m, i, u, v;
    while(scanf("%d%d", &n, &m) == 2){
        getMap(n, m);
        DAG(n);
    }
    return 0;
}

再放一个RE的记忆化搜索。。。:

#include <stdio.h>
#include <string.h>
#define inf 0x7fffffff
#define maxn 100002
#define maxm 1000002

int dp[maxn], id;
struct Node2{
    int first, v;
} head[maxn];
struct Node{
    int to, next;
} E[maxm];
bool in[maxn], out[maxn];

void addEdge(int u, int v)
{
    E[id].to = v;
    E[id].next = head[u].first;
    head[u].first = id++;
}

void getMap(int n, int m)
{
    int i, u, v;
    for(i = 1; i <= n; ++i){
        scanf("%d", &head[i].v);
        head[i].v = -head[i].v;
        in[i] = out[i] = 0; dp[i] = inf;
        head[i].first = -1;
    }
    for(i = 0; i < m; ++i){
        scanf("%d%d", &u, &v);
        addEdge(u, v); in[v] = 1; out[u] = 1;
    }
}

int DFS(int k)
{
    if(dp[k] != inf) return dp[k];
    int i, u, v, ans = inf, tmp;
    for(i = head[k].first; i != -1; i = E[i].next){
        tmp = head[k].v + DFS(E[i].to);
        if(tmp < ans) ans = tmp;
    }
    return dp[k] = ans;
}

void solve(int n)
{
    int i, u, v, ans = inf, tmp;
    for(i = 1; i <= n; ++i)
        if(!out[i]) dp[i] = head[i].v;
    for(i = 1; i <= n; ++i){
        if(!in[i]){
            tmp = DFS(i);
            if(tmp < ans) ans = tmp;
        }
    }
    printf("%d\n", -ans);
}

int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m) == 2){
        getMap(n, m);
        solve(n);
    }
    return 0;
}

POJ3249 Test for Job 【DAG】+【记忆化搜索】

时间: 2024-10-05 12:59:22

POJ3249 Test for Job 【DAG】+【记忆化搜索】的相关文章

NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数,每组测

poj 3249 Test for Job (DAG最长路 记忆化搜索解决)

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8990   Accepted: 2004 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 job

UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)

描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=378 n种方块,给出每一种的长宽高,现在要落起来,上面的方块的长和宽要严格小于下面的方块,问最多落多高. ACM Contest Problems ArchiveUniversity of Valladolid (SPAIN)437 The Tower of BabylonPerhap

由DAG到背包问题——记忆化搜索和递推两种解法

一.问题描述 物品无限的背包问题:有n种物品,每种均有无穷多个.第 i 种物品的体积为Vi,重量为Wi.选一些物品装到一个容量为 C 的背包中,求使得背包内物品总体积不超过C的前提下重量的最大值.1≤n≤100, 1≤Vi≤C≤10000, 1≤Wi≤1000000. 二.解题思路 我们可以先求体积恰好为 i 时的最大重量(设为d[i]),然后取d[i]中的最大值(i ≤ C).与之前硬币问题,"面值恰好为S"就类似了.只不过加了新属性--重量,相当于把原来的无权图改成带权图,即把&q

LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以看到信息. 然后SCC缩点后就形成DAG,直接记忆化搜索,d(u)搜索从u点出发开始传最多能传多少人. 最后就是找答案了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namesp

ZOJ3795 Grouping(强连通分量+缩点+记忆化搜索)

题目给一张有向图,要把点分组,问最少要几个组使得同组内的任意两点不连通. 首先考虑找出强连通分量缩点后形成DAG,强连通分量内的点肯定各自一组,两个强连通分量的拓扑序能确定的也得各自一组. 能在同一组的就是两个强连通分量在不同的从入度0到出度0的强连通分量的路径上. 那么算法很直观就能想到了,用记忆化搜索,d[u]表示从强连通分量u出发到出度为0的强连通分量最少要几个组(最多有几个点). 1 #include<cstdio> 2 #include<cstring> 3 #inclu

路径方案数_mod_SPFA_记忆化搜索_C++

本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 本来是写个 DP 分分钟就 A 了,结果老师要我们写记忆化搜索(无奈脸) 算啦,随手一改又是一个标准的记忆化搜索(目测好像是记忆化搜索容易码一些,而且跑得快一些) 话说不取模也可以A,数据太水 很水的题吧,先 SPFA 跑一遍 2 的最短路,然后记忆化搜索统计方案 不难证明在加上最短路的限制条件后,图变成了一个 DAG 证明:首先有向是显然的,不可能存在两点 x,y,它们的最短路 d[x]>d[y] 又 d[x]<d[y] 若存在一

BNU 20860——Forwarding Emails——————【强连通图缩点+记忆化搜索】

Forwarding Emails Time Limit: 1000ms Memory Limit: 131072KB This problem will be judged on UVA. Original ID: 1244264-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory 2-SAT

hdu1078  记忆化搜索(DP+DFS)

题意:一张n*n的格子表格,每个格子里有个数,每次能够水平或竖直走k个格子,允许上下左右走,每次走的格子上的数必须比上一个走的格子的数大,问最大的路径和. 我一开始的思路是,或许是普通的最大路径和,只是多了可以一次走k个格子这个条件而已,终于能够水过了呢! 紧接着我发现,不止能向左和下走,还可以往回走!这就不能用 for(i=0;i<n;i++)  for(j=0;j<n;j++) 这样的两个循环 dp 掉整个图了,因为当我更新完后面的点可能又会走回来. 并想不到 DFS 的我想到了我是否可以