P1807 最长路(拓扑排序)

一道裸的dag拓扑排序,vector模拟邻接表存出边和权值,dp数组更新最长路。

/*
 展开
题目描述

设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 GG 中 <1,n><1,n> 间的最长路径。

输入格式

输入的第一行有两个整数,分别代表图的点数 n 和边数 m。

第 2 到第 (m+1) 行,每行 3 个整数 u, v,w,代表存在一条从 u 到 v 边权为w的边。

输出格式

输出一行一个整数,代表 1 到 n 的最长路。

若 1 与 n 不联通,请输出 -1。
*/

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int indge[maxn],dp[maxn],bj[maxn];
int n,m;
vector<pair<int,int> >v[maxn];
void topsort()
{
    queue<int>q;
    while(!q.empty())q.pop();
    for(int i=1;i<=n;i++){
        if(!indge[i])q.push(i);
    }
    while(!q.empty()){
        int k=q.front();q.pop();
        for(int i=0;i<v[k].size();i++){
            if(--indge[v[k][i].first]==0)q.push(v[k][i].first);
            if(bj[k]){
                dp[v[k][i].first]=max(dp[v[k][i].first],dp[k]+v[k][i].second);///自身的长度与父亲节点的最长路加上父亲到儿子这条边的长度比较
                bj[v[k][i].first]=1;
             }
        }
    }
}
int main()
{
    cin>>n>>m;
    int a,b,c;
    memset(indge,0,sizeof(indge));
    memset(dp,0,sizeof(dp));
    memset(bj,0,sizeof(bj));
    for(int i=0;i<m;i++){
        cin>>a>>b>>c;
        v[a].push_back(make_pair(b,c));
        indge[b]++;
    }
    dp[n]=-1,bj[1]=1;///初始化dp[n]=-1,输出方便,bj[1]=1,标记1能到达点
    topsort();
    cout<<dp[n]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/mohari/p/12915037.html