传送门:题目
题意:
给一个图,求两点权值累加和的最大值,点的权值可能为负数。
题解:
我们可以先拓扑排序一下,然后从起点到终点dp一下,记录每个点的答案,然后求答案的最大值
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
const int maxv=100010;
const int maxe=1000010;
struct Edge{
int to,next,val;
}edge[maxe];
int cnt,TPOindex;
bool visit[maxv];
int head[maxv],w[maxv],in[maxv],out[maxv],dis[maxv],TPO[maxv];
void init(){
cnt=0;
TPOindex=0;
memset(head,-1,sizeof head);
memset(out,0,sizeof out);
memset(in,0,sizeof in);
memset(visit,false,sizeof visit);
}
void addedge(int from,int to){
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt++;
}
void TopSortDfs(int u){//DFS拓扑排序
visit[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
if(visit[edge[i].to]==false)
TopSortDfs(edge[i].to);
TPO[TPOindex++]=u;
}
void DP(int n){
for(int i=n-1;i>=0;i--){
int u=TPO[i];
for(int j=head[u];j!=-1;j=edge[j].next){
int v=edge[j].to;//从终点开始对每一条边进行松弛,和Bellman_Ford有点像
dis[v]=max(dis[u]+w[v],dis[v]);
}
}
}
void TopSort(int n){
for(int i=1;i<=n;i++)
dis[i]=(in[i]==0?w[i]:-INF);//初始化dis
for(int i=1;i<=n;i++)
if(visit[i]==false)
TopSortDfs(i);
DP(n);
}
int main(void){
int n,m,t1,t2;
while(~scanf("%d%d",&n,&m)){
init();
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=0;i<m;i++){
scanf("%d%d",&t1,&t2);
addedge(t1,t2);
in[t2]++,out[t1]++;
}
TopSort(n);
int ans=-INF;
for(int i=1;i<=n;i++)
if(out[i]==0)
ans=max(ans,dis[i]);
printf("%d\n",ans);
}
return 0;
}