题目连接为:http://poj.org/problem?id=3249
大意如下:
给定n个城市,m个路径,每个城市有对应的收入(可能为负值)。起始城市(source-city)为入度为0的城市,目标城市(target-city)为出度为零的城市。
求出在给定的情况下,从起始城市到目标城市的最大收入。
思路:题目给出的图是DAG,所以对其进行拓扑排序,再利用动态规划方程: dp[v]=max(dp[v],dp[u]+w[v]);
拓扑排序得到的是对图中的点的顺序。
拓扑排序的方法有两种:
一。记录所有点的入度和出度
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.(利用队列,将所有入度为0的点加入到队列中)
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.(邻接表中的每个点的入度减一,将删除的节点按照顺序放到数组中,或对点进行标号,这样形成的就是拓扑序)
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.(当队列为空时,完成对所有点的搜索)
本题的代码就是利用该方法得到拓扑序的。
二。利用DFS
反复利用DFS过程,直到所有点用完。 在DFS过程中,将完成搜索的点放到链表的头部(相当于栈的压栈操作)。
最后形成的链表就是有向图的拓扑序。
#include <algorithm>
#include <bitset>
#include <deque>
#include <functional>
#include <fstream>
#include <list>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <stack>
#include <sstream>
#include <utility>
#include <vector>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <climits>
#define up(i, lower, upper) for(int i = lower; i < upper; i++)
#define down(i, lower, upper) for(int i = upper-1; i >= lower; i--)
using namespace std;
#define MAX_N 100010
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpii;
typedef long long ll;
typedef unsigned long long ull;
const double pi = acos(-1.0);
const double eps = 1.0e-9;
template<class T>
inline bool read(T &n){
T x = 0, tmp = 1; char c = getchar();
while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if (c == EOF) return false;
if (c == '-') c = getchar(), tmp = -1;
while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar();
n = x*tmp;
return true;
}
template <class T>
inline void write(T n) {
if (n < 0) {
putchar('-');
n = -n;
}
int len = 0, data[20];
while (n) {
data[len++] = n % 10;
n /= 10;
}
if (!len) data[len++] = 0;
while (len--) putchar(data[len] + 48);
}
const int MAXN = 100001;
int a[MAXN], ind[MAXN], outd[MAXN], dp[MAXN];
vector<int> e[MAXN];
queue<int> q;
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = 1; i <= n; ++ i)
{
scanf("%d", &a[i]);
e[i].clear();
dp[i] = INT_MIN;
ind[i] = outd[i] = 0;
}
while (m --)
{
int x, y;
scanf("%d%d", &x, &y);
e[x].push_back(y);
++ ind[y];
++ outd[x];
}
for (int i = 1; i <= n; ++ i)
if (!ind[i])
{
dp[i] = a[i];
q.push(i);
}
while (!q.empty())
{
int cur = q.front();
q.pop();
for (int i = 0; i < e[cur].size(); ++ i)
{
dp[e[cur][i]] = max(dp[e[cur][i]], dp[cur] + a[e[cur][i]]);
if (-- ind[e[cur][i]] == 0)
q.push(e[cur][i]);
}
}
int ans = INT_MIN;
for (int i = 1; i <= n; ++ i)
if (!outd[i])
ans = max(ans, dp[i]);
printf("%d\n", ans);
}
return 0;
}