Loading

题解:洛谷 P1137 旅行计划

  • 标签:图论,拓扑,dp

题意

给定一张 \(n\) 个点 \(m\) 条边的 DAG,对于每个 \(i\),求以它为终点最多经过多少个点?

思路

由于是 DAG,求的是终点 \(i\) 经过的所有点,而刚好拓扑序就满足这个。

那么就可以考虑拓扑排序。

\(f_i\) 是以 \(i\) 为终点的最多结点数,那么就有转移方程 \(f_v=max(f_v,f_u+1)\)

在拓扑排序过程中,所有入度为 \(0\)\(v\)\(v\) 可以从其它节点过来,也就是它的前驱 \(u\)

\(u\) 的方案数 \(f_u\) 再加 \(1\)

当然初始化时对于所有入度为 \(0\)\(u\)\(f_u=1\)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,x,y,in[N],f[N];
vector<int> g[N];
void topo(){
	queue<int> q;
	for(int i=1;i<=n;i++) if(in[i]==0) q.push(i),f[i]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto i:g[u]){
			if(--in[i]==0){
				f[i]=f[u]+1;
				q.push(i);
			}
		}
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
		cin>>x>>y;
		g[x].push_back(y),in[y]++;
	}
	topo();
	for(int i=1;i<=n;i++) cout<<f[i]<<endl;
	return 0;
}
posted @ 2024-04-27 21:49  jess1ca1o0g3  阅读(62)  评论(0)    收藏  举报