灭绝树题集
灭绝树 ??? 什么沙雕东西啊 百度好像没有相关介绍啊 研究了一发别人代码 woc 这不是拓扑+倍增吗
回归正题
灭绝树是什么: 灭绝树是一种数据结构 它能解决 DAG图上关键点的问题 即这颗树的性质是 如果v是u的祖先节点 v灭绝了 u也活不下去了 ->灭绝树
怎么构造灭绝树: 我们考虑是一个DAG图 拓扑排序后 连向他的节点均加入到树中 当加入这个节点时 只需要把这个节点挂到lca(对这点连边的节点)下面 然后就能保证其祖先节点gg 他的子树节点也会gg的性质
构造方法: 边跑拓扑的时候 把入度为0的点 加入到树中 倍增维护网上跳的情况
例题1.
2815: [ZJOI2012]灾难
对于A被B吃 则A->B 然后题目保证DAG 直接灭绝树即可
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int du[MAXN];
vector<int>vec[MAXN],v1[MAXN];
queue<int>que;
int f[MAXN][21],dep[MAXN],size[MAXN];
int Lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int tmp=dep[u]-dep[v];
for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];
if(u==v)return u;
for(int i=20;i>=0;i--){
if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
}
return f[u][0];
}
void dfs(int x){
size[x]=1;
for(int i=0;i<v1[x].size();i++){dfs(v1[x][i]);size[x]+=size[v1[x][i]];}
}
int main(){
int n=read();
inc(i,1,n){
int t;
while(scanf("%d",&t)!=EOF){
if(!t)break;
add(t,i);du[i]++;vec[i].pb(t);
}
}
inc(i,1,n)if(!du[i])add(n+1,i),du[i]++,vec[i].pb(n+1);
que.push(n+1);f[n+1][0]=0;dep[n+1]=1;
while(!que.empty()){
int t=que.front();que.pop();
link(t){
du[j->t]--;
if(!du[j->t]){
que.push(j->t);
int lca=t;
for(int k=0;k<vec[j->t].size();k++)lca=Lca(lca,vec[j->t][k]);
f[j->t][0]=lca;dep[j->t]=dep[lca]+1;v1[lca].pb(j->t);
for(int k=1;k<=20;k++)f[j->t][k]=f[f[j->t][k-1]][k-1];
}
}
}
dfs(n+1);
inc(i,1,n)printf("%d\n",size[i]-1);
}
例题2.
codeforces757F. Team Rocket Rises Again
题解:跑出最短路图 然后灭绝树处理
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
const double eps=1e-8;
#define ll long long
const ll inf=1e18;
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<2],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
typedef struct node{
int v;ll d;
friend bool operator<(node aa,node bb){return aa.d>bb.d;}
}node;
ll dis[MAXN];
priority_queue<node>que;
int n,m,s;
void dij(){
inc(i,1,n)dis[i]=inf;
dis[s]=0;que.push((node){s,0});
while(!que.empty()){
node t=que.top();que.pop();
link(t.v){
if(dis[j->t]>dis[t.v]+j->v){
dis[j->t]=dis[t.v]+j->v;
que.push((node){j->t,dis[j->t]});
}
}
}
}
vector<int>vec[MAXN],v1[MAXN];
int du[MAXN],f[MAXN][21],dep[MAXN];
queue<int>q;
int Lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int tmp=dep[u]-dep[v];
for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];
if(u==v)return u;
for(int i=20;i>=0;i--){
if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
}
return f[u][0];
}
int size[MAXN];
void dfs(int x){
size[x]=1;
link(x)dfs(j->t),size[x]+=size[j->t];
}
int main(){
n=read();m=read();s=read();
int u,v,k;
inc(i,1,m)u=read(),v=read(),k=read(),add(u,v,k),add(v,u,k);
dij();
for(int i=1;i<=n;i++){
link(i){
if(dis[i]+j->v==dis[j->t])vec[i].pb(j->t),du[j->t]++,v1[j->t].pb(i);
}
}
memset(h,0,sizeof(h));o=e;
q.push(s);f[s][0]=0;dep[s]=1;
while(!q.empty()){
int t=q.front();q.pop();
for(int i=0;i<vec[t].size();i++){
du[vec[t][i]]--;
if(!du[vec[t][i]]){
q.push(vec[t][i]);
v=vec[t][i];
int lca=t;
for(int j=0;j<v1[v].size();j++)lca=Lca(lca,v1[v][j]);
f[v][0]=lca;dep[v]=dep[lca]+1;add(lca,v,0);
for(int j=1;j<=20;j++)f[v][j]=f[f[v][j-1]][j-1];
}
}
}
dfs(s);
int maxx=0;
inc(i,1,n)if(i!=s)maxx=max(maxx,size[i]);
printf("%d\n",maxx);
}
例题3.
101741L. Increasing Costs
题解:跑出最短路树 然后把边作点拆边构成DAG图 类似例2处理即可
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=4e5+10;
const double eps=1e-8;
#define ll long long
const ll inf=1e18;
using namespace std;
struct edge{int t,v,id;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul,int id){o->t=y;o->v=vul;o->next=h[x];o->id=id;h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
ll dis[MAXN];
typedef struct node{
int v;ll d;
friend bool operator<(node aa,node bb){return aa.d>bb.d;}
}node;
priority_queue<node>que;
int n,m;
void dij(){
inc(i,1,n)dis[i]=inf;
dis[1]=0;que.push((node){1,0});
while(!que.empty()){
node t=que.top();que.pop();
link(t.v){
if(dis[j->t]>t.d+j->v){
dis[j->t]=t.d+j->v;que.push((node){j->t,dis[j->t]});
}
}
}
}
typedef struct Edge{
int u,v,id;
}Edge;
Edge EDge[MAXN<<1];
int du[MAXN];
int f[MAXN<<1][21],dep[MAXN<<1];
queue<int>q;
vector<int>vec[MAXN<<1],v1[MAXN<<1];
int Lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int tmp=dep[u]-dep[v];
for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];
if(u==v)return u;
for(int i=20;i>=0;i--){
if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
}
return f[u][0];
}
int size[MAXN<<1],ans[MAXN];
void dfs(int x){
if(x<=n)size[x]=1;
for(int i=0;i<v1[x].size();i++){
dfs(v1[x][i]);
size[x]+=size[v1[x][i]];
}
if(x>n)ans[x-n]=size[x];
}
int main(){
n=read();m=read();
int u,v,k;
inc(i,1,m)u=read(),v=read(),k=read(),add(u,v,k,i),add(v,u,k,i);
dij();int cnt=0;
inc(i,1,n){
link(i){
if(dis[j->t]==dis[i]+j->v)EDge[++cnt]=(Edge){i,j->t,j->id};
}
}
memset(h,0,sizeof(h));o=e;
for(int i=1;i<=cnt;i++){
add(EDge[i].u,EDge[i].id+n,0,0);du[EDge[i].id+n]++;
vec[EDge[i].id+n].pb(EDge[i].u);
add(EDge[i].id+n,EDge[i].v,0,0);du[EDge[i].v]++;
vec[EDge[i].v].pb(EDge[i].id+n);
}
q.push(1);f[1][0]=0;dep[1]=1;
while(!q.empty()){
int t=q.front();q.pop();
link(t){
du[j->t]--;
if(!du[j->t]){
q.push(j->t);
int lca=t;
for(int k=0;k<vec[j->t].size();k++){
lca=Lca(lca,vec[j->t][k]);
}
f[j->t][0]=lca;dep[j->t]=dep[lca]+1;v1[lca].pb(j->t);
for(int k=1;k<=20;k++)f[j->t][k]=f[f[j->t][k-1]][k-1];
}
}
}
dfs(1);
inc(i,1,m)printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号