给出一张有向图,每个点有点权,现要从一条入度为0的点到一个出度为0的点,问最大点权和
dp数组,dp[i]为点i出的最大值。 我们先求出各个点的最大值。 之后比较出度等于0的点的dp,输出最大的即可。。
那么,我们怎么求各个点的dp。
利用拓扑排序,先让入度为0的点进入,dp等于他们的对应值。之后拓扑即可。 dp[v]=max(dp[v],dp[u]+cost[v]);
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1111111
#define INF 0x3f3f3f3f
struct Edge
{
int to,next;
}edge[maxn];
int n,m,cost[maxn],in[maxn],out[maxn];
int que[maxn],head[maxn],tot,dp[maxn];
void init()
{
tot=0;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
}
void add(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void top_order()
{
for(int i=1;i<=n;i++)
if(!in[i])dp[i]=cost[i];
else dp[i]=-INF;
int res=0;
for(int i=1;i<=n;i++)
if(!in[i])que[res++]=i;
for(int i=0;i<res;i++)
for(int j=head[que[i]];~j;j=edge[j].next)
{
int u=que[i],v=edge[j].to;
dp[v]=max(dp[v],dp[u]+cost[v]);
in[v]--;
if(!in[v])que[res++]=v;
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<=n;i++)scanf("%d",&cost[i]);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
in[b]++,out[a]++;
add(a,b);
}
top_order();
int ans=-INF;
for(int i=1;i<=n;i++)
if(!out[i]&&dp[i]>ans)
ans=dp[i];
printf("%d\n",ans);
}
return 0;
}