POJ 3249 - Test for Job - Topological Order

Test for Job

描述
Dog先生被他的公司解雇了。为了养家糊口,他必须尽快找到一份新工作。如今,由于失业人数不断增加,很难找到工作。因此,一些公司在招聘时经常使用难度较大的测试。
测试是这样的:从一个城市出发,你可以通过一些有方向的道路到达另一个城市。每次你到达一个城市,你可以赚取一些利润或支付一些费用,让这个过程继续下去,直到你到达一个目标城市。
老板会计算你旅行的花费和你刚得到的利润。最后,他会决定你是否能被录用。
为了得到这份工作,Dog先生设法了解了他可能到达的所有城市的净利润Vi(负Vi表示钱是花的而不是赚的)以及城市之间的联系。
没有道路通向的城市为源城市,无通向其他城市道路的城市为目标城市。Dog先生的使命是从一个源头城市出发,选择一条通往目标城市的路线,通过这条路线他可以获得最大的利润。

Input
输入文件包括几个测试用例。
每个测试用例的第一行包含2个整数n和m(1 ≤ n ≤ 100000, 0 ≤ m ≤ 1000000)表示城市和道路的数量。
接下来的n行各包含一个整数。第i行描述了城市i的净利润Vi (0 ≤ |Vi| ≤ 20000)
接下来的m行各包含两个整数x,y,表示有一条从城市x到城市y的道路。
保证每一条路只出现一次,没有办法回到以前的城市。


Output
输出文件为每个测试用例包含一行,其中包含一个整数,表示Dog先生能够获得的最大利润(或花费的最小开支)

Sample Input
6 5
1
2
2
3
3
4
1 2
1 3
2 4
3 4
5 6

Sample Output
7

 

解决方案:有向图,起点入度为0,且需要排序,故使用拓扑排序

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

/**
 ** 解决方案:有向图,起点入度为0,且需要排序,故使用拓扑排序
 *  
 * @author XA-GDD
 *
 */
public class F_TestForJob {
	static int N,M;
	static TopologicalNode [] nodeArr=new TopologicalNode[100002];
	static long ANS;
	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str;  
        StringTokenizer st;
		while((str = br.readLine()) != null) {
			if("".equals(str)) break;
			
            st = new StringTokenizer(str);
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            
			//读取数据
			for(int i=1;i<=N;i++) {
				 st = new StringTokenizer(br.readLine());
				 nodeArr[i] = new TopologicalNode(i,Integer.parseInt(st.nextToken()));
			}
			for(int i=1;i<=M;i++) {
				st = new StringTokenizer(br.readLine());
				int start = Integer.parseInt(st.nextToken());
				int end = Integer.parseInt(st.nextToken());
				nodeArr[start].adjList.add(end);
				nodeArr[start].outDegree +=1;
				nodeArr[end].inDegree += 1;
			}
            topologicalOrder();
            System.out.println(ANS);
		}
	}
	
	static void topologicalOrder() {
		Queue<Integer> queue = new LinkedList<Integer>();
		for(int i=1;i<=N;i++) {
			if(nodeArr[i].inDegree==0) {
				nodeArr[i].cost = nodeArr[i].val;
				queue.add(i);
			}
		}
		ANS = (long)Integer.MIN_VALUE;
		while(!queue.isEmpty()) {
			int curr = queue.poll();
	
			for(int i=0;i<nodeArr[curr].adjList.size();i++) {
				int next = nodeArr[curr].adjList.get(i);
				if(nodeArr[next].inDegree==0) {
					continue;
				}
				nodeArr[next].inDegree -= 1;
				nodeArr[next].cost = Math.max(nodeArr[next].cost, nodeArr[curr].cost+nodeArr[next].val);
				if(nodeArr[next].inDegree==0) {
					queue.add(next);
				}
			}
		}
		
		for(int i=1;i<=N;i++) {
			if(nodeArr[i].outDegree==0) {
				ANS = Math.max(ANS, nodeArr[i].cost);
			}
		}
		
	}

}

//定义节点对象
class TopologicalNode{
	int index;		//节点index
	int val;		//权值
	int inDegree;	//入度
	int outDegree;	//出度
	int cost;		//节点累计权值
	ArrayList<Integer> adjList;

	TopologicalNode(int index, int val){
		this.index = index;
		this.val = val;
		this.inDegree=0;
		this.outDegree=0;
		this.cost=Integer.MIN_VALUE;
		adjList = new ArrayList<Integer>();
	}
}

  

posted @ 2021-09-03 16:13  晓暮云  阅读(55)  评论(0)    收藏  举报