一道裸的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; }