Tarjan 求调
查看原帖
Tarjan 求调
666273
Inscription_Assassin楼主2024/9/20 19:34

RT,不知道哪里的问题,思路就是缩点拓扑然后DAG正反dp,但是样例都过不了

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 1e5 + 5;
const int M = N << 1;

int n, m;
int x[N], y[N];
int h[N], e[M], ne[M], idx;
int hc[N], vc[M], nc[M], tc;
int stk[N], ins[N], c[N], dfn[N], low[N];
int f[N][2], in[N];
bool v[N][2];
vector<int> scc[N];
int top, num, cnt;

void add(int a, int b)
{
	e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}

void add_c(int a, int b)
{
	vc[++tc] = b, nc[tc] = hc[a], hc[a] = tc, in[b]++;
}

void tarjan(int x)
{
	dfn[x] = low[x] = ++num;
	stk[++top] = x, ins[x] = 1;
	for (rint i = h[x]; i; i = ne[i])
	{
		int y = e[i];
		if (!dfn[y])
		{
			tarjan(y);
			low[x] = min(low[x], low[y]);
		}
		else if (ins[y]) low[x] = min(low[x], dfn[y]);
	}
	if (dfn[x] == low[x])
	{
		cnt++; int y;
		do
		{
			y = stk[top--], ins[y] = 0;
			c[y] = cnt, scc[cnt].push_back(y);
		} while (x != y);
	}
}

void toposort(int k)
{
	queue<int> q;
	for (rint i = 1; i <= cnt; i++)
	    if (!in[i])
	        q.push(i);
	while (!q.empty())
	{
		int x = q.front();
		q.pop();
		f[x][k] += scc[x].size();
		for (rint i = hc[i]; i; i = nc[i])
		{
			int y = vc[i];
			in[y]--;
			if (v[x][k])
			{
				v[y][k] = 1;
				f[y][k] = max(f[x][k], f[y][k]);
			}
			if (!in[y]) q.push(y);
		}
	}
}

signed main()
{
	cin >> n >> m;
	for (rint i = 1; i <= m; i++)
	{
		cin >> x[i] >> y[i];
		add(x[i], y[i]);
	}
	for (rint i = 1; i <= n; i++)
	    if (!dfn[i])
	        tarjan(i);
	int s = c[1];
	v[s][0] = v[s][1] = 1;
	for (rint x = 1; x <= idx; x++)
	{
		for (rint i = h[x]; i; i = ne[i])
		{
			int y = e[i];
			if (c[x] == c[y]) continue;
			add_c(c[x], c[y]);
		}
	}
	toposort(0);
	memset(hc, 0, sizeof hc);
	memset(vc, 0, sizeof vc);
	memset(nc, 0, sizeof nc);
	memset(in, 0, sizeof in);	
	tc = 0;
	for (rint x = 1; x <= idx; x++)
	{
		for (rint i = h[x]; i; i = ne[i])
		{
			int y = e[i];
			if (c[x] == c[y]) continue;
			add_c(c[y], c[x]);
		}
	}
	toposort(1);
	int ans = scc[s].size();
	for (rint i = 1; i <= cnt; i++)
    {
    	int a = c[x[i]], b = c[y[i]];
		if (v[a][1] && v[b][0])
		{
			ans = max(ans, f[a][1] + f[b][0] - (int)scc[s].size());
		}
	}
	cout << ans << endl;
	return 0;
}
2024/9/20 19:34
加载中...