Luogu P1137 旅行计划

Luogu P1137 旅行计划

可以发现,因为只能往东边走,并且有入度为$0$的起点,因此这是一个有向无环图,可以进行拓扑排序,求出拓扑序列。
那么我们要拓扑序列怎么做呢?由于拓扑序列中,前面的点总是后面的点的前驱,因此可以进行DP。
而DP的状态转移方程也很明显,这个城市只能由前面的城市转移过来,因此有方程:$$dis[v]=max(dis[v],dis[u]+1)$$

#include<bits/stdc++.h>
#define N 100010
#define M 200010

using namespace std;

int n,m,cnt;
int deg[N],head[N],dis[N];

struct node {
	int nxt,to;
}edge[M];

void addEdge(int u,int v) {
	edge[++cnt]=(node){head[u],v};
	head[u]=cnt;
	deg[v]++;
	return;
}

void Read() {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		addEdge(u,v);
	}
	return;
}

void Init() {
	for(int i=1;i<=n;i++) {
		dis[i]=1;
	}
	return;
}

void Topo() {
	queue <int> q;
	for(int i=1;i<=n;i++) {
		if(deg[i]==0) {
			q.push(i);
		}
	}
	while(!q.empty()) {
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=edge[i].nxt) {
			int t=edge[i].to;
			deg[t]--;
			if(deg[t]==0) {
				dis[t]=dis[x]+1;
				q.push(t);
			}
		}
	}
	return;
}

void Print() {
	for(int i=1;i<=n;i++) {
		printf("%d\n",dis[i]);
	}
	return;
}

int main()
{
	Read();
	Init();
	Topo();
	Print();
	return 0;
}
posted @ 2019-10-31 22:28  WalkerV  阅读(128)  评论(0编辑  收藏  举报