POJ 3249 Test for Job
求职
| 时限: 5000MS | 内存限制: 65536K | |
| 提交总数: 15100 | 接受的: 3387 |
描述
狗被他的公司解雇了。为了养家糊口,他必须尽快找到新工作。如今,很难找到工作,因为失业人数在不断增加。因此,一些公司经常对他们的招聘使用严格的测试。
测试是这样的:从源城市开始,您可能会通过一些有向路到达其他城市。每次到达城市,您都可以赚取利润或支付一定的费用。让此过程继续进行,直到到达目标城市为止。老板将计算您在旅途中花费的费用和刚刚获得的利润。最后,他将决定是否可以聘用您。
为了找到工作,狗先生设法了解了他可能达到的所有城市的净利润V i(负V i表示花了钱而不是赚了钱)以及城市之间的联系。一个没有道路通向它的城市是一个源城市,一个没有道路通向其他城市的城市是一个目标城市。狗先生的任务是从来源城市开始,并选择一条通往目标城市的路线,以使他能够获得最大的利润。
输入值
输入文件包括几个测试用例。
每个测试用例的第一行包含2个整数Ñ和米(1≤ Ñ ≤100000,0≤米≤1000000)指示城市,道路的数目。
接下来的n行每个包含一个整数。第i行描述了城市i的净利润,V i(0≤| V i |≤20000)
接下来的m行每行包含两个整数x,y,指示从城市x到城市y的道路通向。可以保证每条道路仅出现一次,并且无法返回到先前的城市。
每个测试用例的第一行包含2个整数Ñ和米(1≤ Ñ ≤100000,0≤米≤1000000)指示城市,道路的数目。
接下来的n行每个包含一个整数。第i行描述了城市i的净利润,V i(0≤| V i |≤20000)
接下来的m行每行包含两个整数x,y,指示从城市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; } }

浙公网安备 33010602011771号