Longest Path
7623 分钟
原文链接:https://www.cnblogs.com/Time25/p/19699216.html
题目大意
这个是一个有向无环图,
![image]()
然后求最长的那个路径,
错误解法
1 2 3 4 5 6 7 8 9
| void solve() { int n,m,rec=INT_MIN;cin>>n>>m; vector<int>dp(n+1); while(m--){ int x,y;cin>>x>>y; dp[y]=max(dp[y],dp[x]+1); rec=max(dp[y],rec); } cout<<rec<<endl;
|
似乎把问题想的太简单了
错误原因
3 2
2 3
1 2
1->2->3,应该是3
但是你的写法会让答案是1,但是正确答案是2
因为你在处理2的时候,2是0,但是后面会跟3连,这个时候2又变成1了,但是1没有被记录进去
究其原因就是,题目不一定都是按照拓扑序拍好的,
什么叫拓扑序?拓扑序(Topological Order),简单来说,就是“按先后依赖关系排好的一条直线顺序”。
有向无环图才有拓扑序,是才有,不是一定有
题目给的例子你都能过,因为题目的例子都非常阴间的按照拓扑序排好的
正确解法1 DFS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const int MAXN = 100005; vector<int> adj[MAXN]; int dp[MAXN]; int dfs(int u){ if(dp[u]!=-1)return dp[u]; int rec=0; for(int v:adj[u]){ rec=max(rec,dfs(v)+1); } return dp[u]=rec; } void solve(){ int n,m; cin>>n>>m; while(m--){ int x,y; cin>>x>>y; adj[x].pb(y); } memset(dp,-1,sizeof(dp)); int ans=0; for(int i=1;i<=n;i++){ ans=max(ans,dfs(i)); } cout<<ans<<endl; }
|
解释
枚举每一个点,看从哪一个点出发的距离是最大的
正确解法2 拓扑序+dp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void solve2(){ int n,m;cin>>n>>m; vector<int>dp(n+1); vector<int>in_degree(n+1); vector<vector<int>>adj(n+1); queue<int>q; int ans=0; while(m--){ int x,y;cin>>x>>y; adj[x].pb(y); in_degree[y]++;
} for(int i=1;i<=n;i++){ if(in_degree[i]==0){ q.push(i); } } while(!q.empty()){ int kk=q.front(); ans=max(ans,dp[kk]); q.pop(); for(int v:adj[kk]){ dp[v]=max(dp[v],dp[kk]+1); in_degree[v]--; if(in_degree[v]==0)q.push(v); } } cout<<ans<<endl; }
|
解释,就如上面那个例子,只有2没有前驱的时候,才可以方向的进行
dp[3]=max(dp[3],dp[2]+1),我们维护一个队列,这个队列记录的就是那些没有前驱的点
// TRAINING LOG · 第 18 / 76 篇训练记录 · 成文于 2026.03.10 · 夜间 21:48