zoukankan      html  css  js  c++  java
  • Tarjan 算法

    时间复杂度: (O(n))

    数组含义

    (dfn[u]) 时间戳,节点 (u) 的访问顺序

    (low[u]) , 从节点 (u) 出发能访问到的 (dfn) 最小的节点

    求强连通分量

    The Cow Prom S

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 1e4 + 10;
    vector<int>G[N];
    int n, m;
    
    int dfn[N], low[N], cnt, ans;
    stack<int>stk;
    
    void dfs(int u) {
    	dfn[u] = low[u] = ++cnt;
    	stk.push(u);
    	for (int v : G[u]) {
    		if (not dfn[v]) {
    			dfs(v);
    		}
    		low[u] = min(low[u], low[v]);
    	}
    	if (dfn[u] == low[u]) {
    		if (stk.top() != u)ans++;
    		while (stk.top() != u)stk.pop();
    		stk.pop();
    	}
    }
    int main() {
    	ios::sync_with_stdio(0); cin.tie(0);
    	cin >> n >> m;
    	for (int i = 0; i < m; i++) {
    		int a, b; cin >> a >> b; G[a].push_back(b);
    	}
    	for (int i = 1; i <= n; i++) {
    		if (!dfn[i])dfs(i);
    	}
    	cout << ans << endl;
    }
    

    割点

    【模板】割点(割顶)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 2e4 + 10;
    vector<int>G[N];
    int n, m;
    
    int dfn[N], low[N], cnt, ans, cut[N];
    stack<int>stk;
    
    void dfs(int u,int rt) {
    	dfn[u] = low[u] = ++cnt;
    	stk.push(u); int ch = 0;
    	for (int v : G[u]) {
    		if (not dfn[v]) {
    			dfs(v, rt);
    			low[u] = min(low[u], low[v]);
    			if (low[v] >= dfn[u] and u != rt) cut[u] = 1;
    			if (u == rt)ch++;
    		}
    		else low[u] = min(low[u], dfn[v]);
    	}
    	if (ch > 1 and u == rt)cut[u] = 1;
    }
    int main() {
    	ios::sync_with_stdio(0); cin.tie(0);
    	cin >> n >> m;
    	for (int i = 0; i < m; i++) {
    		int a, b; cin >> a >> b; 
    		G[a].push_back(b); G[b].push_back(a);
    	}
    	for (int i = 1; i <= n; i++) {
    		if (!dfn[i])dfs(i, i);
    	}
    	for (int i = 1; i <= n; i++)ans += cut[i];
    	cout << ans << endl;
    	for (int i = 1; i <= n; i++) {
    		if (cut[i])cout << i << " ";
    	}cout << endl;
    }
    

    缩点

    【模板】缩点

    #include<bits/stdc++.h>
    using namespace std;
    template<typename T = int>
    inline const T read()
    {
        T x = 0, f = 1;
        char ch = getchar();
        while (ch < '0' || ch > '9') {
            if (ch == '-') f = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9') {
            x = (x << 3) + (x << 1) + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    
    template<typename T>
    inline void write(T x, bool ln)
    {
        if (x < 0) {
            putchar('-');
            x = -x;
        }
        if (x > 9) write(x / 10, false);
        putchar(x % 10 + '0');
        if (ln) putchar(10);
    }
    const int N = 1e4 + 10;
    int n, m;
    vector<int>G[N];
    int w[N], dfn[N], low[N], cnt, vis[N], col[N];
    int f[N], scnt;
    stack<int>stk;
    void dfs(int u) {
    	stk.push(u); vis[u] = 1;
    	dfn[u] = low[u] = ++cnt;
    	for (int v : G[u]) {
    		if (not dfn[v]) {
    			dfs(v);
    			low[u] = min(low[u], low[v]);
    		}
    		else if (vis[v]) low[u] = min(low[u], dfn[v]);
    	}
    	if (dfn[u] == low[u]) {
    		++scnt; int v;
    		do {
    			v = stk.top(); stk.pop();
    			vis[v] = 0;
    			col[v] = scnt;
    			f[scnt] += w[v];
    		} while (v != u);
    	}
    }
    
    int in[N], dp[N];
    vector<int>g[N];
    
    int main() {
    	n = read(),m = read();
    	for (int i = 1; i <= n; i++)w[i] = read();
    	for (int i = 1; i <= m; i++) {
    		int a = read(),b = read();
    		G[a].push_back(b);
    	}
    	for (int i = 1; i <= n; i++) {
    		if (not dfn[i])dfs(i);
    	}
    	for (int i = 1; i <= n; i++) {
    		int u = col[i];
    		for (int v : G[i]) {
    			int x = col[v];
    			if (x == u)continue;
    			g[u].push_back(x);
    			in[x]++;
    		}
    	}
    	queue<int>Q;
    	for (int i = 1; i <= scnt; i++) {
    		if (not in[i])Q.push(i);
    		dp[i] = f[i];
    	}
    	int ans = 0;
    
    	while (not Q.empty()) {
    		int u = Q.front(); Q.pop();
    		for (int v : g[u]) {
    			dp[v] = max(dp[v], f[v] + dp[u]);
    			in[v]--;
    			if (not in[v]) {
    				Q.push(v);
    			}
    		}
    	}
    	for (int i = 1; i <= scnt; i++) {
    		ans = max(ans, dp[i]);
    	}
    	printf("%d
    ", ans);
    
    }
    
  • 相关阅读:
    [DB] 数据库的连接
    JS leetcode 翻转字符串里的单词 题解分析
    JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
    JS leetcode 搜索插入位置 题解分析
    JS leetcode 杨辉三角Ⅱ 题解分析
    JS leetcode 寻找数组的中心索引 题解分析
    JS leetcode 移除元素 题解分析
    JS leetcode 最大连续1的个数 题解分析
    JS leetcode 两数之和 II
    JS leetcode 反转字符串 题解分析
  • 原文地址:https://www.cnblogs.com/sduwh/p/13974863.html
Copyright © 2011-2022 走看看