POJ 3249 Test for Job

求职
时限: 5000MS   内存限制: 65536K
提交总数: 15100   接受的: 3387

描述

狗被他的公司解雇了。为了养家糊口,他必须尽快找到新工作。如今,很难找到工作,因为失业人数在不断增加。因此,一些公司经常对他们的招聘使用严格的测试。

测试是这样的:从源城市开始,您可能会通过一些有向路到达其他城市。每次到达城市,您都可以赚取利润或支付一定的费用。让此过程继续进行,直到到达目标城市为止。老板将计算您在旅途中花费的费用和刚刚获得的利润。最后,他将决定是否可以聘用您。

为了找到工作,狗先生设法了解了他可能达到的所有城市的净利润i(负i表示花了钱而不是赚了钱)以及城市之间的联系。一个没有道路通向它的城市是一个源城市,一个没有道路通向其他城市的城市是一个目标城市。狗先生的任务是从来源城市开始,并选择一条通往目标城市的路线,以使他能够获得最大的利润。

输入值

输入文件包括几个测试用例。
每个测试用例的第一行包含2个整数Ñ(1≤ Ñ ≤100000,0≤≤1000000)指示城市,道路的数目。
接下来的n行每个包含一个整数。i行描述了城市i的净利润i(0≤| i |≤20000)
接下来的m行每行包含两个整数xy,指示从城市x到城市y的道路通向可以保证每条道路仅出现一次,并且无法返回到先前的城市。

输出量

输出文件针对每个测试用例包含一行,其中包含一个整数,指示Dog能够获得的最大利润(或花费的最低支出)

样本输入

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

样本输出

7





经分析需要拓扑排序


我们先回忆一下
拓扑过程
1. 找出入度为0的点。
2. 去除该店,将该点连接的其他点入度进行减一操作。
3. 继续寻找入度为0的点。重复以上操作。最后就可以得到去除点的顺序为拓扑排序


本地需要注意点
1. 数据量比较大 用 long 型数据
2. 入度为0的点可能有多个需要注意
3. 出度为0的点 就是目标点 最后在外侧进行判断取最大利益值,
因为有可能孤立的点是最终结果,所以不能在循环内进行判断



两套代码供给参考


package pro.proclass.chaopengfan;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class VjudgeK {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while (br.ready()) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int n = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());
            ArrayList<Integer>[] arr = new ArrayList[n+1];
            long[] profit = new long[n+1];
            long[] in = new long[n+1];
            long[] out = new long[n+1];
            long[] dp = new long[n+1];

            for (int i = 0; i < n; i++) {
                st = new StringTokenizer(br.readLine());
                profit[i+1] = Integer.parseInt(st.nextToken());
                arr[i+1] = new ArrayList<Integer>();
            }

            for (int i = 0; i < m; i++) {
                st = new StringTokenizer(br.readLine());
                int a = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
                arr[a].add(b);
                out[a]++;
                in[b]++;
            }

            LinkedList<Integer> queue = new LinkedList<Integer>();
            Arrays.fill(dp, Integer.MIN_VALUE);
            for (int i = 1; i <= n; i++) {
                if(in[i] == 0) {
                    queue.add(i);
                    dp[i] = profit[i];
                }
            }

            long ans = Integer.MIN_VALUE;

            while (!queue.isEmpty()){
                Integer cur = queue.poll();

                for (int j = 0; j < arr[cur].size(); j++) {
                    Integer p = arr[cur].get(j);
                    if(in[p] == 0) continue;

                    in[p]--;

                    dp[p] = Math.max(dp[p], profit[p] + dp[cur]);
                    if(in[p] == 0) {
                        queue.add(p);
                    }
                }
            }

            for (int i = 1; i <= n; i++) {
                if(out[i] == 0) { // 出度为0, 获取最大利益
                    ans = Math.max(ans, dp[i]);
                }
            }

            System.out.println(ans);
        }
    }
}

 

第二套 采用链式向前星 效率能高很多
package pro.proclass.tielintang;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

import static java.lang.Integer.parseInt;

public class TestforJob3249 {
    private static int n, m, cnt;
    private static int[] dp, head;
    private static Point[] points;
    private static Edge[] edge;

    public static void add_edge(int u, int v) {
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        while (br.ready()) {
            st = new StringTokenizer(br.readLine());
            n = parseInt(st.nextToken());
            m = parseInt(st.nextToken());
            dp = new int[n+1];
            head = new int[n+1];
            points = new Point[n+1];
            edge = new Edge[m];
            cnt = 0;
            Arrays.fill(head, -1);
            Arrays.fill(dp, Integer.MIN_VALUE);
            for (int i = 0; i < m; i++) {
                edge[i] = new Edge();
            }

            for (int i = 1; i <= n; i++) {
                st = new StringTokenizer(br.readLine());
                points[i] = new Point();
                points[i].weight = parseInt(st.nextToken());
            }

            for (int i = 0; i < m; i++) {
                st = new StringTokenizer(br.readLine());
                int s = parseInt(st.nextToken());
                int e = parseInt(st.nextToken());
                points[s].out++;
                points[e].in++;
                add_edge(s, e);
            }

            topSort();

            long answer = Integer.MIN_VALUE;

            for (int i = 1; i <= n; i++) {
                if(points[i].out == 0) { // 出度为0, 获取最大利益
                    answer = Math.max(answer, dp[i]);
                }
            }

            System.out.println(answer);
        }
    }

    private static void topSort() {
        LinkedList<Integer> priorityQueue = new LinkedList<Integer>();

        for (int i = 1; i <= n; i++) {
            if(points[i].in == 0) { // 入度为0的初始化dp
                dp[i] = points[i].weight;
                priorityQueue.add(i);
            }
        }

        while (!priorityQueue.isEmpty()) {
            Integer now = priorityQueue.poll();

            for (int i = head[now]; i >= 0; i = edge[i].next) {
                int v = edge[i].to;
                if(points[v].in == 0) continue;
                dp[v] = Math.max(dp[v], dp[now] + points[v].weight);
                points[v].in--;
                if(points[v].in == 0) priorityQueue.add(v);
            }
        }
    }

    static class Edge {
        int to;
        int next;
    }

    static class Point {
        int in;
        int out;
        int weight;
    }
}

 






posted @ 2020-10-12 09:51  姓蜀名黍  阅读(215)  评论(0)    收藏  举报