• [模板] [拓扑序列]


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

    寻找过程就是不断找入度为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;
    }
  • 相关阅读:
    C#重载操作符的那点事
    Winform最小化托盘
    C#多线程传参
    GridView事件大全
    测试2
    测试
    FindFileByContent
    JavaScriptCallCSharp js调用C#属性与方法
    GroupBy
    查询指定属性的文件
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270378.html
Copyright © 2020-2023  润新知