【BZOJ4010】【HNOI2015】菜肴制作

本文介绍了一种利用反向建边进行拓扑排序的方法,并提供了完整的代码实现。该方法的时间复杂度为O(D*(N+M)),适用于解决依赖关系问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目链接】

【思路要点】

  • 反向建边拓补排序就行。
  • 时间复杂度\(O(D*(N+M))\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	100005
int d[MAXN], n, m, now, tot, to;
int home[MAXN], ans[MAXN], cnt[MAXN], colour[MAXN];
vector <int> a[MAXN];
bool func() {
	int l = 1, r = 0;
	static int q[MAXN];
	for (int i = 1; i <= n; i++)
		if (d[i] == 0) q[++r] = i;
	while (l <= r) {
		int tmp = q[l];
		for (unsigned i = 0; i < a[tmp].size(); i++) {
			d[a[tmp][i]]--;
			if (d[a[tmp][i]] == 0) q[++r] = a[tmp][i];
		}
		l++;
	}
	return r < n;
}
void visit(int pos) {
	if (colour[pos] != now) return;
	colour[pos] = to;
	tot++;
	for (unsigned i = 0; i < a[pos].size(); i++)
		visit(a[pos][i]);
}
int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++)
			a[i].clear();
		memset(d, 0, sizeof(d));
		for (int i = 1; i <= m; i++) {
			int x, y;
			scanf("%d%d", &x, &y);
			a[y].push_back(x);
			d[x]++;
		}
		if (func()) {
			printf("Impossible!\n");
			continue;
		}
		memset(home, 0, sizeof(home));
		memset(ans, 0, sizeof(ans));
		memset(cnt, 0, sizeof(cnt));
		memset(colour, 0, sizeof(colour));
		home[0] = n + 1; cnt[0] = n + 1;
		for (int i = 1; i <= n; i++) {
			now = colour[i];
			tot = 0; to = i;
			visit(i);
			home[i] = home[now] - cnt[now] + tot;
			cnt[i] = tot;
			cnt[now] -= tot;
			ans[home[i]] = i;
		}
		for (int i = 1; i < n; i++)
			printf("%d ", ans[i]);
		printf("%d \n", ans[n]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值