【CF1182D】Complete Mirror【树的重心】
生活随笔
收集整理的這篇文章主要介紹了
【CF1182D】Complete Mirror【树的重心】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
傳送門
題意:給一棵NNN個結(jié)點的樹,你需要欽定一個根,使得所有深度相同的點的度數(shù)相同。
N≤100000N \leq 100000N≤100000
用腦子想一想,就是根節(jié)點直接相連的子樹都長得一模一樣。
如果根節(jié)點度數(shù)大于1,我們發(fā)現(xiàn)它把整棵樹均勻地分成了若干份。所以根節(jié)點是重心。
O(N)O(N)O(N)找重心檢查一下
如果根節(jié)點度數(shù)等于1,也就是拉了一條鏈下去
由于是遞歸的,所以走到有岔路的地方就是岔路口所在子樹的重心
因為兩棵樹合并后的重心在原來的重心的路徑上,所以整棵樹的重心在鏈上。
所以沿一條鏈走到底就可以了。
但如果有多條路,說明重心是岔路口。因為下面長得一模一樣,所以即使是鏈,長度也都相同。
所以找兩條長度不同的鏈的頂部搜一下即可。
復(fù)雜度O(N)O(N)O(N)
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #define MAXN 100005 #define MAXM 200005 using namespace std; struct edge{int u,v;}e[MAXM]; int head[MAXN],nxt[MAXM],cnt; void addnode(int u,int v) {e[++cnt]=(edge){u,v};nxt[cnt]=head[u];head[u]=cnt; } int siz[MAXN],dep[MAXN],n; void dfs(int u) {siz[u]=1;for (int i=head[u];i;i=nxt[i])if (!dep[e[i].v]){dep[e[i].v]=dep[u]+1;dfs(e[i].v);siz[u]+=siz[e[i].v];} } int maxp[MAXN]={0x7fffffff}; int findroot() {dfs(dep[1]=1);int rt=0;for (int u=1;u<=n;u++){for (int i=head[u];i;i=nxt[i])if (dep[e[i].v]==dep[u]+1)maxp[u]=max(maxp[u],siz[e[i].v]);if (n-siz[u]>maxp[u]) maxp[u]=n-siz[u];if (maxp[u]<maxp[rt]) rt=u;}return rt; } int tmp[MAXN]; bool check(int rt) {memset(siz,0,sizeof(siz));memset(dep,0,sizeof(dep));memset(tmp,0,sizeof(tmp));dep[rt]=1;dfs(rt);for (int u=1;u<=n;u++){int deg=0;for (int i=head[u];i;i=nxt[i])++deg;if (!tmp[dep[u]]) tmp[dep[u]]=deg;if (tmp[dep[u]]!=deg) return false;}return true; } int line(int u,int f) {if (!nxt[head[u]]) return u;if (nxt[nxt[head[u]]]) return 0;int i=head[u];if (e[i].v==f) i=nxt[i];return line(e[i].v,u); } int len[MAXN]; inline bool cmp(const int& a,const int& b){return dep[a]<dep[b];} int main() {scanf("%d",&n);for (int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addnode(u,v);addnode(v,u);}int rt=findroot();if (check(rt)){printf("%d\n",rt);return 0;}for (int i=head[rt];i;i=nxt[i])len[++len[0]]=line(e[i].v,rt);sort(len+1,len+len[0]+1,cmp);if (len[1]&&check(len[1])){printf("%d\n",len[1]);return 0;}if (len[len[0]]&&check(len[len[0]])){printf("%d\n",len[len[0]]);return 0;}puts("-1");return 0; }總結(jié)
以上是生活随笔為你收集整理的【CF1182D】Complete Mirror【树的重心】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【CF1204D】Kirk and a
- 下一篇: w10如何创建本地连接