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);
    
    }
    
  • 相关阅读:
    linux 常用命令
    books list
    开发文化,沟通、会议、总结
    编程资源
    敏捷开发流程
    服务器安全部署指南
    服务器应用部署规范
    单元测试
    弱弱的页码问题
    实验A javaScript XML数据操作按姓名查询
  • 原文地址:https://www.cnblogs.com/sduwh/p/13974863.html
Copyright © 2011-2022 走看看