题目链接
题目大意就是在一个有向无环图上,具体我也说不清楚,看题目链接。目的学习支配树,支配树分三种,一个是树上,二是有向无环图,三是一般有向图,这里是针对的是有向无环图是的支配树的构造。
代码:
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define ll long long
#define maxx 65544
using namespace std;
int n;
vector<int> g[maxx];
int ind[maxx];
queue<int> q;
int order[maxx],cnt;
void topo()
{
for(int i=1;i<=n;i++)if(!ind[i])q.push(i);
while(q.size())
{
int u=q.front();q.pop();
order[++cnt]=u;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(--ind[v]==0)q.push(v);
}
}
}
int f[maxx][18],N;
int fa[maxx];
int dep[maxx];
vector<int> _g[maxx];
void update(int x)
{
f[x][0]=fa[x];
for(int i=1;i<=N;i++)
f[x][i]=f[f[x][i-1]][i-1];
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=N;i>=0;i--)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return x;
for(int i=N;i>=0;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[y][0];
}
void buildTree()
{
dep[n+1]=1;
fa[n+1]=n+1;
for(int i=n;i>=1;i--)
{
int u=order[i];
if(g[u].size()==0)
{
_g[n+1].push_back(u);
dep[u]=2;
fa[u]=n+1;
f[u][0]=n+1;
continue;
}
int v=g[u][0];
for(int j=1;j<g[u].size();j++)v=lca(v,g[u][j]);
fa[u]=v;_g[v].push_back(u);
dep[u]=dep[v]+1;
update(u);
}
}
int siz[maxx];
void dfs(int u)
{
siz[u]=1;
for(int i=0;i<_g[u].size();i++)
{
dfs(_g[u][i]);
siz[u]+=siz[_g[u][i]];
}
}
int main()
{
cin>>n;N=ceil(log2(n));
int x;
for(int i=1;i<=n;i++)
{
for(;;)
{
scanf("%d",&x);
if(!x)break;
g[i].push_back(x);
ind[x]++;
}
}
topo();
buildTree();
//for(int i=1;i<=n;i++)cout<<i<<" "<<fa[i]<<endl;
dfs(n+1);
for(int i=1;i<=n;i++)printf("%d\n",siz[i]-1);
return 0;
}
本文介绍了一种在有向无环图(DAG)上构建支配树的方法,通过拓扑排序和最近公共祖先(LCA)算法,实现对DAG的深入分析,适用于算法学习和竞赛。
1万+

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



