算法应该是正确的,但是全 TLE 了...
查看原帖
算法应该是正确的,但是全 TLE 了...
9315
zhyh楼主2020/10/9 12:42

rt,怀疑是本机和评测机运行时有区别,就第一个点来说,本机运行 0.03s,评测直接 TLE ...懵逼...

先说一下我的思路:在拓扑排序时,对于每一个节点 x:

  1. 先对其所有食物节点进行拓扑;
  2. 然后选择其中一个食物节点(为了优化我选了深度最小的节点),令其作为倍增树上当前节点 x 的父亲,然后初始化 x 有关倍增 lca 的信息;
  3. 求当前节点 x 的所有食物节点在倍增树上的公共祖先,令其作为答案树上当前节点 x 的父亲;

然后在答案树上累加答案就行了。复杂度应该是 O(MlgN)

然而全TLE了qwq,求教 dalao...

代码:(fst1 是原有向图,fst2 是答案树,倍增树只用存倍增数组就行了)

#include <ctime>
#include <cstdio>
#include <iostream>
using namespace std;
const int inf  = 2147483647;
const int MAXN = 100005;
struct edge {
    int v, pre;
} e[MAXN<<2];
int N, fst1[MAXN], fst2[MAXN], tote;
int vis[MAXN];
int lg[MAXN], dep[MAXN], fa[MAXN][35];
int ans[MAXN];

inline int read()
{
    register int o = 0, oo = 0;
    register char c = getchar();
    while (c < '0' || c > '9') oo |= (c == '-'), c = getchar();
    while (c >='0' && c <='9') o = (o<<3)+(o<<1)+(c&15), c = getchar();
    return oo ? -o : o;
}
void adde1(int a, int b, int k) { e[k] = (edge){b, fst1[a]}, fst1[a] = k;}
void adde2(int a, int b, int k) { e[k] = (edge){b, fst2[a]}, fst2[a] = k;}
int lca(int a, int b)
{
	if (dep[a] < dep[b]) a ^= b ^= a ^= b;
	while (dep[a] > dep[b]) a = fa[a][lg[dep[a]-dep[b]]];
	if (a == b) return a;
	for (int i=lg[dep[a]]; i>=0; i--)
		if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
	return fa[a][0];
}
int toposort(int x) // while building the tree
{
    vis[x] = 1;
    for (int o=fst1[x]; o; o=e[o].pre)
		if (!vis[e[o].v]) toposort(e[o].v);
	if (fst1[x]) {
		int mind = inf, f;
		for (int o=fst1[x]; o; o=e[o].pre)
			if (dep[e[o].v] < mind)
				mind = dep[e[o].v], f = e[o].v;
		fa[x][0] = f, dep[x] = dep[f] + 1;
		for (int i=1; i<=lg[dep[x]]; i++)
			fa[x][i] = fa[fa[x][i-1]][i-1];
		int anc = x;
		for (int o=fst1[x]; o; o=e[o].pre)
			anc = lca(anc, e[o].v);
		adde2(anc, x, ++tote);
	}
}
void init()
{
	N = read();
    for (int i=1; i<=N; i++) {
        int j = read();
        if (!j) adde1(i, 0, ++tote);
        for (; j;) {
            adde1(i, j, ++tote);
            j = read();
        }
    }
}
int solve(int x)
{
	for (int o=fst2[x]; o; o=e[o].pre) ans[x] += solve(e[o].v) + 1;
	return ans[x];
}
void work()
{
	for (int i=1; i<=N; i++) lg[i] = lg[i-1] + ((1<<(lg[i-1]+1)) == i);
    for (int i=1; i<=N; i++) if (!vis[i]) toposort(i);
	solve(0);
	for (int i=1; i<=N; i++) printf("%d\n", ans[i]);
//	printf("Time used = %.2f\n", (double)clock() / CLOCKS_PER_SEC);
}
int main()
{
//	freopen("P2597_1.in", "r", stdin);
//	freopen("output.out", "w", stdout);
	init();
	work();
}
2020/10/9 12:42
加载中...