[模板] [拓扑序列]

拓扑序列有很多用途, 比如判环, 将树上 / 图上的问题转化为序列上的问题再处理等等

寻找过程就是不断找入度为0的点添加到Q尾部

如果得到的拓扑序列长度不等于N 则说明有环

void toposort(int n)
{
	queue <int> Q;

	for(int i = 0; i < n; ++i)
	{
		if(deg[i] == 0)
			Q.push(i);
	}

	while(!Q.empty())
	{
		int pos = Q.front();
		Q.pop();

		arr.push_back(pos);

		for(int x : edge[pos])
		{
			if(! --deg[x])
				Q.push(x);
		}
	}
}

例题 可达性统计

https://www.acwing.com/problem/content/166/

 此题可以用拓扑序+暴力合并解决

原因:

题目给出了一个DAG 则必有合法拓扑序

反向遍历拓扑序 则有在 i 之前的点都不可能指向 i 

所以用bitset存储状态从顶至底合并即可

/*
    Zeolim - An AC a day keeps the bug away
*/

//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int INF = 0x3f3f3f3f;
const int MAXN = 3e4 + 10;
const ll MOD = 1e9 + 7;

std::vector <int> edge[MAXN];

bitset <MAXN> cnt[MAXN];

int deg[MAXN] = {0};

vector <int> arr;

void toposort(int n)
{
	queue <int> Q;

	for(int i = 0; i < n; ++i)
	{
		if(deg[i] == 0)
			Q.push(i);
	}

	while(!Q.empty())
	{
		int pos = Q.front();
		Q.pop();

		arr.push_back(pos);

		for(int x : edge[pos])
		{
			if(! --deg[x])
				Q.push(x);
		}
	}
}

void solve()
{
	for(int i = arr.size() - 1; i >= 0; --i)
	{
		int now = arr[i];

		cnt[now][now] = true;

		for(auto x : edge[now])
		{
			cnt[now] |= cnt[x];
		}
	}
}

int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);     cout.tie(0);
    //freopen("D://test.in", "r", stdin);
    //freopen("D://test.out", "w", stdout);

	int n, m, from, to;

	cin >> n >> m;

	for(int i = 0; i < m; ++i)
		cin >> from >> to, edge[from].push_back(to), ++deg[to];

	toposort(n);

	solve();

	for(int i = 1; i <= n; ++i)
	{
		cout << cnt[i].count() << '
';
	}

    return 0;
}
原文地址:https://www.cnblogs.com/zeolim/p/12270378.html