POJ 3249 拓扑排序+DP

貌似是道水题。TLE了几次。把所有的输入输出改成scanf 和 printf ,有吧队列改成了数组模拟。然后就AC 了。2333333....

Description:

MR.DOG 在找工作的过程中呢。遇见了这样一个问题。有n个城市,m条小道。然后要从入度为0的点出发,出度为0的点结束,中途经过的城市呢,都是要付费的。负数表示花费。正数表示收益。然后让你求收益最大或者说花费最少的总值。

貌似。BFS和DFS都会超时。不妨一试。附代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#define maxn 100005
#define maxm 1000005
#define inf 2100000000
using namespace std;

struct Arc
{
    int point;
    int next_arc;
};
//node 存储每个顶点,arc存储每条边。node[i]表示第i个顶点指向的第一条边在arc中的位置。next_arc表示和这条边同样出发点的下一条边在arc中的位置。
Arc arc[maxm];
int node[maxn], val[maxn];
//ind 和 outd 数组表示顶点的入度和出度 dp数组表示到达每个点的的最大收益
int ind[maxn], outd[maxn], dp[maxn];
// 数组模拟队列 tot表示总共加入的边的数量
int tot, front, rear;
int q[maxn];

void insert(int u, int v)    // 加入从u指向v的一条边
{
    arc[tot].next_arc = node[u];
    arc[tot].point = v;
    node[u] = tot++;
}

void init()
{
    tot = 0;
    memset(node, -1, sizeof(node));
    memset(ind, 0, sizeof(ind));
    memset(outd, 0, sizeof(outd));
}

void topsort()  // 拓扑排序+DP
{
    while(front <= rear)
    {
        int x = q[front++];
        for (int e=node[x]; e!=-1; e=arc[e].next_arc)
        {
            int temp = arc[e].point;
            ind[temp]--;
            dp[temp] = max(dp[temp], dp[x] + val[temp]);
            if (ind[temp] == 0)
            {
                q[++rear] = temp;
            }
        }
    }
}

int main()
{
    int n, m, x, y;
    while(~scanf("%d%d", &n, &m))
    {
        init();
        front = 0, rear = -1;
        for (int i=1; i<=n; ++i)
        {
            scanf("%d", &val[i]);
        }
        for (int i=0; i<m; ++i)
        {
            scanf("%d%d", &x, &y);
            insert(x, y);
            ind[y]++;
            outd[x]++;
        }
        for (int i=1; i<=n; ++i)
        {
           dp[i] = -inf;
        }
        for (int i=1; i<=n; ++i)
        {
            if (ind[i] == 0)
            {
                q[++rear] = i;
                dp[i] = val[i];
            }
        }
        topsort();
        int ans = -inf;
        for (int i=1; i<=n; ++i)
        {
            if (outd[i] == 0)
            ans = max(ans, dp[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}

时间: 2024-12-21 06:51:19

POJ 3249 拓扑排序+DP的相关文章

POJ 3249 Test for Job 拓扑排序+DP

http://poj.org/problem?id=3249 题意: 给一个有向无环图DAG(不一定联通),每个点有权值,入度为0的点为起点,出度为0的点为终点,选择一个起点走到一个终点,使得路上的权和最大. 分析: dp[to] = max(dp[from]) + value[to],然后先拓扑排序保证状态正确转移即可,终点做标记,如果是终点则尝试更新答案. update:因为点权可以为负,所以程序里用dp[i] == -1表示未访问过该点是有问题的,不过没有遇上会卡掉这种情况的数据=.= 1

poj 4084:拓扑排序

poj 4084:拓扑排序 很好的题目,恶心的算法 描述 给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前. 输入 若干行整数,第一行有2个数,分别为顶点数v和弧数a,接下来有a行,每一行有2个数,分别是该条弧所关联的两个顶点编号. v<=100, a<=500 输出 若干个空格隔开的顶点构成的序列(用小写字母). 样例输入 6 8 1 2 1 3 1 4 3 2 3 5 4 5 6 4 6 5 样例输出 v1 v3 v2 v6 v4 v5 解题方案 显然这是有向图,然

Poj 1094 拓扑排序 水题

Sad..这么水的题WA了无数发,题目要看仔细啊,留下来做个警告把 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #i

[Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易可以想到一个做法,就是魔改迪杰斯特拉做法: 如果一个点可以更新到达其他点的距离,那个点的方案数就是这个点的方案数:如果一个点所更新出来的距离和之前的相等,那个点的方案数加等当前点的方案数. 用式子可以表现为: f[j]=f[i] (dis[j]>dis[i]+x)   f[j]+=f[i] (dis

POJ 3249 拓扑+dp

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

POJ3249Test for Job(拓扑排序+DP)

题意就是给一个有向无环图,每个点都有一个权值,求从入度为0的点到出度为0点路径上经过点(包括起点终点)的权值和的最大值. 分析: 注意3点 1.本题有多组数据 2.可能有点的权值是负数,也就是结果可能为负,初值要设为负无穷. 3.入度或出度为0的点不止一个. 注意以上几点本题就很简单了,用到DP dis[i]:=max(dis[j],dis[i]+w[j])在拓扑排序过程同时进行即可. 考前练练拓扑排序和指针. 代码: program test; type point=^node; node=r

poj 2367 拓扑排序

题目链接:http://poj.org/problem?id=2367 题目大意:就是进行拓扑排序,先给你一个数n,代表1~n,对于每个数有一系列的指向,最后将这些数进行排列出来..就是简单的拓扑排序. 首先拓扑排序应该有两种实现的方法.. 一种是用dfs进行每个节点的搜索,最后进行回溯,这样的话很容易就能明白先找出来的应该是后面的数,而最后找出来的应该是之前的数,因为是回溯出来的嘛..所以可以使用一个栈来进行答案的存储,因为栈的特性就是后压入的先弹出. dfs实现的思想:利用一个数组来存储每个

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

NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)

神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性,怎么办呢?拓扑排序. 把最短路上的点和零边的点拉出来跑拓扑排序,如果有零环的话必定度数不为0,而且要注意零环必须在<=最短路+k的路径上才输出-1,这个就用刚刚跑出来的1起点到n起点的最短路来判断就好了. 然后先按拓扑序DP出i相同的,然后再DP不在最短路上或者零边的. #include<iost