[ZJOI2012]灾难

OJ题号:BZOJ2815、洛谷2597

思路:

先将所有的“生产者”连接至0号点“太阳”,然后用kahn求拓扑序。 、
易证一种生物会灭绝当且仅当他的所有食物均灭绝,
而所有食物均灭绝当且仅当他们的LCA灭绝。
按照拓扑序依次将各点加入新图,同时求该点所有食物的LCA,将该点作为LCA的儿子。
DFS遍历求各点后代数量。

注意倍增时不能直接循环到logN,而要循环到log2(dep)。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<queue>
 5 #include<cmath>
 6 inline int getint() {
 7     int ch;
 8     while(!isdigit(ch=getchar()));
 9     int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return x;
12 }
13 const int N=65535,logN=17;
14 std::vector<int> c[N],p[N];
15 std::queue<int> top;
16 int anc[N][logN]={0},dep[N]={0},in[N]={0};
17 void kahn(const int x) {
18     std::queue<int> q;
19     q.push(x);
20     while(!q.empty()) {
21         int v=q.front();
22         q.pop();
23         top.push(v);
24         for(unsigned int i=0;i<c[v].size();i++) {
25             if(!--in[c[v][i]]) q.push(c[v][i]);
26         }
27     }
28     top.pop();
29 }
30 std::vector<int> newc[N];
31 inline void swap(int &a,int &b) {
32     int t;
33     t=a;
34     a=b;
35     b=t;
36 }
37 inline int LCA(int a,int b) {
38     if(dep[a]<dep[b]) swap(a,b);
39     for(int i=(int)log2(dep[a]);i>=0;i--) {
40         if(dep[a]-(1<<i)>=dep[b]) a=anc[a][i];
41     }
42     if(a==b) return a;
43     for(int i=(int)log2(dep[a]);i>=0;i--) {
44         if(anc[a][i]!=anc[b][i]) a=anc[a][i],b=anc[b][i];
45     }
46     return anc[a][0];
47 }
48 int ans[N]={0};
49 void getans(const int x) {
50     for(unsigned int i=0;i<newc[x].size();i++) {
51         getans(newc[x][i]);
52         ans[x]+=ans[newc[x][i]]+1;
53     }
54 }
55 int main() {
56     int n=getint();
57     for(int i=1;i<=n;i++) {
58         for(int x=getint();x;x=getint()) {
59             p[i].push_back(x);
60             c[x].push_back(i);
61             in[i]++;
62         }
63         if(!p[i].size()) {
64             c[0].push_back(i);
65             p[i].push_back(0);
66             in[i]=1;
67         }
68     }
69     kahn(0);
70     while(top.size()) {
71         int v=top.front();
72         top.pop();
73         int lca=p[v][0];
74         for(unsigned int i=1;i<p[v].size();i++) lca=LCA(lca,p[v][i]);
75         newc[lca].push_back(v);
76         anc[v][0]=lca,dep[v]=dep[lca]+1;
77         for(int i=1;i<=(int)log2(dep[v]);i++) anc[v][i]=anc[anc[v][i-1]][i-1];
78     }
79     getans(0);
80     for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
81     return 0;
82 }

 

posted @ 2017-07-11 07:52  skylee03  阅读(148)  评论(0编辑  收藏  举报