POJ 3249 拓扑排序 DP

传送门:题目

题意:

给一个图,求两点权值累加和的最大值,点的权值可能为负数。

题解:

我们可以先拓扑排序一下,然后从起点到终点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;
}
    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/shadandeajian/article/details/82532881
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞