CodeForces-734E Anton and Tree 树的直径
題目大意:
給定一棵有n個(gè)節(jié)點(diǎn)的樹,有黑點(diǎn)白點(diǎn)兩種節(jié)點(diǎn).
每一次操作可以選擇一個(gè)同種顏色的聯(lián)通塊將其染成同一種顏色
現(xiàn)在給定一個(gè)初始局面問最少多少步可以讓樹變?yōu)榧兩?
題解:
首先我們拿到這棵樹時(shí)先將其縮點(diǎn)
然后我們手中的樹就變成了一棵黑白相間的黑白樹.
那么我們現(xiàn)在就是每次選擇一個(gè)節(jié)點(diǎn)使其變色,都會(huì)使得這個(gè)節(jié)點(diǎn)相鄰的所有節(jié)點(diǎn)合并進(jìn)來.
所以我們找度數(shù)最大的合并就好了啊
我們現(xiàn)在把這棵樹想象成由若干條路徑組成的.
那么我們每次合并都會(huì)使某些路徑的長(zhǎng)度最多減少2
所以我們可以自然而然地想到一定是樹的直徑花費(fèi)的操作次數(shù)最大.
所以我們將一棵樹化作一條鏈上面連著許多其他的分支的形式.
手模幾個(gè)樣例就話發(fā)現(xiàn)答案實(shí)際上是\([\frac{len+1}{2}]\)len為直徑長(zhǎng)度.
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; inline void read(int &x){x=0;char ch;bool flag = false;while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x; } const int maxn = 200010; int belong[maxn],nodecnt; int col[maxn]; struct Graph{struct Edge{int to,next;}G[maxn<<1];int head[maxn],cnt;void add(int u,int v){G[++cnt].to = v;G[cnt].next = head[u];head[u] = cnt;} #define v G[i].tovoid dfs1(int u,int f){if(col[u] != col[f]) belong[u] = ++ nodecnt;else belong[u] = belong[f];for(int i = head[u];i;i=G[i].next){if(v == f) continue;dfs1(v,u);}return ;}int dis[maxn],p;void dfs2(int u,int f){for(int i = head[u];i;i=G[i].next){if(v == f) continue;dis[v] = dis[u] + 1;dfs2(v,u);}if(dis[p] < dis[u]) p = u;} #undef v }g1,g2; int main(){int n;read(n);for(int i=1;i<=n;++i) read(col[i]);for(int i=1,u,v;i<n;++i){read(u);read(v);g1.add(u,v);g1.add(v,u);}belong[1] = ++ nodecnt;g1.dfs1(1,1);for(int u=1;u<=n;++u){for(int i = g1.head[u];i;i=g1.G[i].next){if(belong[g1.G[i].to] != belong[u]){g2.add(belong[u],belong[g1.G[i].to]);}}}g2.dfs2(1,1);int u = g2.p;memset(g2.dis,0,sizeof g2.dis);g2.dfs2(u,u);int ans = (g2.dis[g2.p] + 1)/2;printf("%d\n",ans);return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/Skyminer/p/6613127.html
總結(jié)
以上是生活随笔為你收集整理的CodeForces-734E Anton and Tree 树的直径的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 写日历的一些总结(二)
- 下一篇: 软件测试技术lab2——Selenium