1.普通的树状数组+dfs
2.但是1e5直接dfs确实可能RE,所以需要手写模拟栈
3.前向星比vector快一倍左右
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 2e5 + 5;
struct node{
int v,next;
}ns[maxn];
int head[maxn],cnt;
int st[maxn],ed[maxn],te = 0;
int tr[maxn];
int n,p;
int stk[maxn],top = 0;
bool vis[maxn];
//1e5 dfs溢出RE
//void dfs(int u)
//{
// st[u] = ++te;
// int t = head[u];
// while(t != -1){
// if(!st[ns[t].v]) dfs(ns[t].v);
// t = ns[t].next;
// }
// ed[u] = te;
//}
//手写模拟栈
void dfs_stk(int rt)
{
memset(vis, 0, sizeof(vis));
stk[++top] = rt;
while(top){
int u = stk[top];
if(vis[u]){
ed[u] = te;
top --;
continue;
}
vis[u] = 1;
st[u] = ++te;
int t = head[u];
while(t != -1){
if(!vis[ns[t].v]) stk[++top] = ns[t].v;
t = ns[t].next;
}
}
}
void add(int x,int k)
{
while(x <= n){
tr[x] += k;
x += (x & -x);
}
}
int query(int x)
{
int ans =0 ;
while(x){
ans += tr[x];
x -= (x & -x);
}
return ans;
}
void init()
{
cnt = 0;
memset(head,-1,sizeof(head));
memset(st, 0, sizeof(st));
memset(ed, 0, sizeof(ed));
te = 0;
memset(tr, 0, sizeof(tr));
top = 0;
}
void addedge(int u,int v)
{
ns[cnt].v = v;
ns[cnt].next = head[u];
head[u] = cnt;
cnt ++;
}
int main()
{
int u,v;
while(scanf("%d%d",&n,&p) != EOF)
{
if(n == 0 && p == 0) break;
init();
for(int i = 0;i < n - 1;i ++) {
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v, u);
}
dfs_stk(p);
// for (int i = 1; i <= n; i ++) {
// printf("%d %d %d\n",i,st[i],ed[i]);
// }
for(int i = 1;i <= n;i ++){
printf("%d%c",query(ed[i]) - query(st[i] - 1),i == n ? '\n' : ' ');
add(st[i],1);
}
}
return 0;
}
本文介绍了一种结合树状数组、DFS算法及手动栈模拟的优化方案来解决大规模图遍历问题。通过前向星表示法提升效率,并提供完整的C++实现代码,适用于处理含有1e5节点的大规模图数据。
2万+

被折叠的 条评论
为什么被折叠?



