代码堆砌

发布时间 2023-04-19 16:29:42作者: Ciaxin

连通分量

通过 Tanjar 对有向图缩点
 #include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 7, inf = 1e9 + 7;

struct edge {
	int u, v;
} e[N];

int dfn[N], lt[N], st[N], low[N], a[N], siz[N], f[N], indu[N];
int n, m, tim, ans = -inf;

queue <int> q;

vector <int> g[N], G[N];

inline void tanjar(int u)
{
	low[u] = dfn[u] = ++ tim;
	st[++ st[0]] = u;
	for (int v : g[u])
	{
		if (!dfn[v])
		{
			tanjar(v);
			low[u] = min(low[v], low[u]);
		}
		else if (!lt[v])
		{
			low[u] = min(low[u], dfn[v]);
		}
	}
	if (dfn[u] == low[u])
	{
		lt[u] = ++ lt[0];
		siz[lt[0]] += a[u];
		while (st[st[0]] != u)
		{
			lt[st[st[0]]] = lt[0];
			siz[lt[0]] += a[st[st[0]]];
			st[0] --;
		}
		st[0] --;
	}
}

int main()
{
	scanf("%lld%lld",&n,&m);
	for (int i = 1; i <= n; ++ i)
	{
		scanf("%lld",&a[i]);
	}
	for (int i = 1; i <= m; ++ i)
	{
		scanf("%lld%lld",&e[i].u,&e[i].v);
		g[e[i].u].push_back(e[i].v);
	}
	for (int i = 1; i <= n; ++ i)
	{
		if (!dfn[i]) tanjar(i);
	}
	for (int i = 1; i <= m; ++ i)
	{
		int u = lt[e[i].u];
		int v = lt[e[i].v];
		if (u == v) continue;
		G[u].push_back(v);
		indu[v] ++;
	}
	for (int i = 1; i <= lt[0]; ++ i)
	{
//		f[i] = -inf;
		if (indu[i] == 0) 
		{
			q.push(i);
			f[i] = siz[i];
		}
	}
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		for (int v : G[u])
		{
			f[v] = max(f[v], f[u]+siz[v]);
			indu[v] --;
			if(indu[v] == 0) q.push(v); 
		}
	}
	for (int i = 1; i <= lt[0]; ++ i) ans = max(ans, f[i]);
	printf("%lld",ans); 
	return 0;
}
通过 Tanjar 所求出的割点
#include <bits/stdc++.h>
using namespace std;

int low[21000], dfn[21000], n, m, tim, root, cnt; 
vector <int> g[21000];
bool vis[21000];

inline void tanjar(int u, int fa)
{
	dfn[u] = low[u] = ++ tim;
	int col = 0;
	for (int v : g[u])
	{
		if (!dfn[v])
		{
			col ++;
			tanjar(v, u);
			low[u] = min(low[u], low[v]); 
            // 两种割点的判断方式
			if (u == root && col > 1)
			{
				if (!vis[u]) vis[u] = 1, cnt ++;
			}
			if (u != root && dfn[u] <= low[v]) 
			{
				if (!vis[u]) vis[u] = 1, cnt ++;
			}
		}
		else if (fa != v)
		{
			low[u] = min(low[u], dfn[v]);
		}
	}
}

int main()
{
	cin >> n >> m;
	for (int i = 1, u, v; i <= m; ++ i)
	{
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for (int i = 1; i <= n; ++ i)
	{
		if (!dfn[i]) 
		{
			root = i;
			tanjar(i, 0);
		}
	}
	cout << cnt << '\n'; // 割点数量
	for (int i = 1; i <= n; ++ i)
	{
		if (vis[i]) cout << i << ' '; // 割点
	}
	return 0;
}