BZOJ2815 拓撲排序 LCA

2022-05-20 02:30:36 字數 2867 閱讀 6950

作為乙個dag圖,結點之間又有這麼明顯的等級之分,很容易想到的是拓撲排序。

但是不管是正向的拓撲排序還是逆向的拓撲排序感覺都不是特別容易的能解決這個問題。

但事實上只要知道乙個十分關鍵的點:乙個物種會滅絕的必要條件是當且僅當另乙個物種滅絕。

例如樣例給的當中,小強的滅絕僅和草是否滅絕有關,和牛羊無關。

因此事實上這個圖的關係可以變為一棵樹的關係,乙個點會滅絕當且僅當他的祖先滅絕。

怎麼確定乙個點的父親結點?考慮動態建樹,以最底層的食物為起點開始拓撲排序,乙個結點被訪問意味著它所有的食物已經被加入樹中,那麼他的父親就是他所有食物的lca

最後求乙個樹的字首和就可以了

乙個小細節是倍增lca需要一邊建樹一邊維護稀疏表。

#include #include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define for(i, x, y) for(int i=x;i<=y;i++)

#define _for(i, x, y) for(int i=x;i>=y;i--)

#define mem(f, x) memset(f,x,sizeof(f))

#define sca(x) scanf("%d", &x)

#define sca2(x,y) scanf("%d%d",&x,&y)

#define sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define scl(x) scanf("%lld",&x);

#define pri(x) printf("%d\n", x)

#define prl(x) printf("%lld\n",x);

#define clr(u) for(int i=0;i<=n;i++)u[i].clear();

#define ll long long

#define ull unsigned long long

#define mp make_pair

#define pii pair#define pil pair#define pll pair#define pb push_back

#define fi first

#define se second typedef vector

vi;int read()

while (c >= '

0'&&c <= '

9')return x*f;}

const

double eps = 1e-9

;const

int maxn = 1e5 + 10

;const

int inf = 0x3f3f3f3f

;const

int mod = 1e9 + 7

; int

n,m,k;

struct

edgeedge[

1000000

],redge[maxn],tedge[maxn];

inthead[maxn],tot;

intrhead[maxn],rtot;

intthead[maxn],ttot;

intpre[maxn];

void

init()

void add(int u,int

v)void tadd(int u,int

v)const

int sp = 20

;int

ind[maxn];

intpa[maxn][sp],dep[maxn];

void dfs(int u,int

la)}

int lca(int u,int

v) }

return u == v ? u : pa[u][0];}

intmain()

}int root = 0

; pa[root][

0] = 0; dep[root] = 1

;

for(int i = 1; i < sp; i ++) pa[root][i] = pa[pa[root][i - 1]][i - 1

]; queue

q;for(int i = 1; i <= n ; i ++)

}while(!q.empty())

tadd(fa,u);

pa[u][

0] = fa; dep[u] = dep[fa] + 1

;

for(int i = 1; i < sp ; i ++) pa[u][i] = pa[pa[u][i - 1]][i - 1

];

for(int i = rhead[u]; ~i ; i =redge[i].next)

}dfs(root,-1

);

for(int i = 1; i <= n ; i ++) pri(pre[i]);

return0;

}

bzoj2815 災難 拓撲排序 lca

按照出題人的題解 我們需要構造一顆 滅絕樹 即對於滅絕樹上的兩個點x,y,如果x為y的祖先,則x的滅亡會直接導致y的滅亡。下面進行構造 首先進行拓撲排序,然後按照排序的逆序構造,保證對於圖中的任意x 都能使x構造前,已經完成構造。然後找到在滅絕樹上面的位置,顯然在滅絕樹上的公共祖先的滅絕會導致全部滅...

bzoj2815 ZJOI2012 災難 支配樹

沒事學習一下新演算法 反正也不是很難,wc講過的拖到現在真是不好意思啊。個人感覺基本上恨少考這個東西 題意 給你乙個dag,對於每乙個點去掉以後有多少個點不能從入度為0的點到達。那麼這明顯就是支配樹,只要我刪的這個點是必經點,那麼我在支配樹上的所有兒子都不能到達,那麼每個點的答案就是他在支配樹的上的...

python 拓撲排序 Python 拓撲排序

python 拓撲排序 在圖論中,由乙個有向無環圖的頂點組成的序列,當且僅當滿足下列條件時,稱為該圖的乙個拓撲排序 英語 topological sorting 每個頂點出現且只出現一次 若a在序列中排在b的前面,則在圖中不存在從b到a的路徑。print 拓撲排序結果 g.topologicalso...