【DP】【拓扑排序】road 题解

来源:互联网 发布:怎么做淘宝货源供应商 编辑:程序博客网 时间:2024/05/16 07:48

给一个图,从一个入度为零的点到一个出度为零的点,求点权和最大。

跑dp的同时也要跑拓扑排序,dp[i]表示从一个入度为0的点到i位置的最大分数。然后将i之后的点全部入度减1,接着进行dp。

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <set>#include <queue>#include <algorithm>#include <vector>#include <cstdlib>#include <cmath>#include <ctime>#include <stack>#define INF 2147483647#define LL long long#define clr(x) memset(x, 0, sizeof x)#define digit (ch <  '0' || ch >  '9')using namespace std;template <class T> inline void read(T &x) {    int flag = 1; x = 0;    register char ch = getchar();    while( digit) { if(ch == '-')  flag = -1; ch = getchar(); }    while(!digit) { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); }    x *= flag;}const int maxm = 2000005;const int maxn = 100005;struct data { int nxt,to; } e[maxm];int n,m,val[maxn],in[maxn],out[maxn],tail[maxn],tot;LL dp[maxn],ans;queue<int> q;inline void add(int x, int y) { e[++tot].nxt = tail[x], tail[x] = tot, e[tot].to = y; }int main() {    freopen("road.in","r",stdin);    freopen("road.out","w",stdout);    read(n); read(m);    memset(val, -0x3f3f3f3f, sizeof val);    for(register int i = 1; i <= n; i++) read(val[i]);    for(register int u, v, i = 1; i <= m; i++) read(u), read(v), add(u, v), in[v]++, out[u]++;    for(register int i = 1; i <= n; i++) if(!in[i]) q.push(i), dp[i] = val[i];    while(!q.empty()){        int u = q.front(); q.pop();        for(register int i = tail[u]; i; i = e[i].nxt) {            int v = e[i].to; in[v]--;            if(dp[v] == dp[0]) dp[v] = dp[u];            else dp[v] = max(dp[v], dp[u]);            if(!in[v]) dp[v] += val[v], q.push(v);        }    }    for(register int i = 1; i <= n; i++) if(!out[i]) ans = max(ans, dp[i]);    cout << ans << endl;    return 0;}
原创粉丝点击