【思维题 细节】loj#6042. 「雅礼集训 2017 Day7」跳蚤王国的宰相
作者:互联网
挂于±1的细节……
题目描述
跳蚤王国爆发了一场动乱,国王在镇压动乱的同时,需要在跳蚤国地方钦定一个人来做宰相。
由于当时形势的复杂性,很多跳蚤都并不想去做一个傀儡宰相,带着宰相的帽子,最后还冒着被打倒并杀头的危险,然而有一只跳蚤却想得与众不同最时尚。
本来他打算去教书,他已经发表了自己在学术方面的见解,获得了很多跳蚤们的赞同,但是这时听说跳蚤国要钦定宰相,他毅然打断了想去教书的想法,他觉得只要为了国家利益,自己的生死都可以不管,哪里能因为工作能给自己带来灾祸或者福分就去避开或者接近这份工作呢?所以他决定站出来接了这份工作。
然而当时国王的钦定方式很奇怪,跳蚤王国可以看作一棵树,国王认为宰相必须更好的为跳蚤服务,所以他会选择一个到所有节点距离和最小的节点,并在这个节点中钦定,如果有多个节点满足距离和最小则任选一个。
然而跳蚤国的动乱实在是太厉害了,以至于树的形态可能也会发生改变,也就是说,树上可能会有若干条边消失,如果这个情况出现的话一定会有同样数目的边出现,以保证整个结构仍然是一棵树。
现在这个跳蚤想知道每个节点中的跳蚤如果要被钦定,至少需要多少条边消失(当然也会有同样数目的边出现)。作为这只跳蚤的一名真正的粉丝,你能帮他解决这个问题吗?
数据范围:n≤10^6
题目分析
首先分析这里“合法”节点的性质。
1 #include<bits/stdc++.h> 2 const int maxn = 1000035; 3 const int maxm = 2000035; 4 5 int n,root,cnt,leg,sum; 6 int size[maxn],son[maxn],anc[maxn],ans[maxn]; 7 int edgeTot,head[maxn],nxt[maxm],edges[maxm]; 8 9 int read() 10 { 11 char ch = getchar(); 12 int num = 0, fl = 1; 13 for (; !isdigit(ch); ch=getchar()) 14 if (ch=='-') fl = -1; 15 for (; isdigit(ch); ch=getchar()) 16 num = (num<<1)+(num<<3)+ch-48; 17 return num*fl; 18 } 19 void addedge(int u, int v) 20 { 21 edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot; 22 edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot; 23 } 24 void getRoot(int x, int fa, bool tag) 25 { 26 son[x] = 0, size[x] = 1; 27 for (int i=head[x]; i!=-1; i=nxt[i]) 28 { 29 int v = edges[i]; 30 if (v==fa) continue; 31 getRoot(v, x, tag), size[x] += size[v]; 32 son[x] = std::max(son[x], size[v]); 33 } 34 son[x] = std::max(son[x], n-size[x]); 35 if (tag&&son[x] < son[root]) root = x; 36 } 37 bool cmp(int x, int y) 38 { 39 return size[x] > size[y]; 40 } 41 void dfs(int x, int fa, int c) 42 { 43 ans[x] = (leg-1)+((n-c-size[x])*2 > n); 44 for (int i=head[x]; i!=-1; i=nxt[i]) 45 if (edges[i]!=fa) dfs(edges[i], x, c); 46 } 47 int main() 48 { 49 memset(head, -1, sizeof head); 50 n = read(); 51 for (int i=1; i<n; i++) addedge(read(), read()); 52 root = 0, son[root] = n; 53 getRoot(1, 0, true); 54 getRoot(root, 0, false); 55 for (int i=head[root]; i!=-1; i=nxt[i]) 56 anc[++cnt] = edges[i]; 57 std::sort(anc+1, anc+cnt+1, cmp); 58 for (int i=1; i<=cnt; i++) 59 { 60 sum += size[anc[i]], ++leg; 61 if (sum*2 >= (n)) break; 62 } 63 for (int i=1; i<=cnt; i++) 64 dfs(anc[i], root, sum-std::max(size[anc[i]], size[anc[leg]])); 65 for (int i=1; i<=n; i++) printf("%d\n",ans[i]); 66 return 0; 67 }
END
标签:ch,loj,Day7,钦定,6042,int,maxn,节点,跳蚤 来源: https://www.cnblogs.com/antiquality/p/10665865.html