【POJ - 3249】Test for Job(DAG线性求带负权的最长路,dp)
題干:
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?Viof 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?i,?Vi?(0 ≤ |?Vi| ≤ 20000)?
The next m lines each contain two integers?x,?y?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 6Sample Output
7Hint
解題報告:
? 因為有負權值所以初值要注意初始值要是-INF,并且只能用vis數組來標記是否走過,不能用dp[v]=-1來判斷是否走過,因為這里的dp有負權值所以不能把-1當成非法狀態。
? 這題也可以拓撲排序,每次彈出入度為0的頂點來更新其他節點,不斷維護e[i].v的最大值(因為e[i].u這個值是完成值也就是保證了是最優解,所以只能用我為人人法去更新),這樣也可以做到On的復雜度。
其實兩種方法一個是遞推dp(按照拓撲序當dp的階段)一個是記憶化搜索,本質是一樣的。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e6 + 5; const int INF = 0x3f3f3f3f; struct Edge {int to,ne; } e[MAX]; int head[MAX],in[MAX],out[MAX],tot,val[MAX],n,m; void add(int u,int v) {e[++tot].to = v;;e[tot].ne = head[u];head[u] = tot; } int dp[MAX],vis[MAX]; int dfs(int cur,int rt) {if(vis[cur] == 1) return dp[cur];vis[cur] = 1;int res = -INF;//int res = val[cur];這樣寫的話應該就錯了不信一會你自己試試 for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].to;res = max(res,dfs(v,cur));}if(head[cur] == -1) return dp[cur] = val[cur];else return dp[cur] = res + val[cur]; } int main() {while(~scanf("%d%d",&n,&m)) {tot=0;for(int i = 1; i<=n; i++) head[i] = -1,in[i]=out[i]=vis[i]=0,dp[i] = 0;for(int i = 1; i<=n; i++) scanf("%d",val+i);for(int u,v,i = 1; i<=m; i++) {scanf("%d%d",&u,&v),add(u,v);in[v]++;out[u]++;}int ans = -INF;//如果用0來賦初值的話呢?會有什么后果》 for(int i = 1; i<=n; i++) {if(in[i] == 0) {ans = max(ans,dfs(i,-1));}}printf("%d\n",ans);} return 0 ; }?
總結
以上是生活随笔為你收集整理的【POJ - 3249】Test for Job(DAG线性求带负权的最长路,dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡申请可以撤销吗 电话取消态度要强硬
- 下一篇: 支付宝上面的理财怎么不见了?支付宝为什么