bzoj1131: [POI2008]Sta

給出一個N個點的樹,找出一個點來,以這個點爲根的樹時,所有點的深度之和最大
Input
給出一個數字N,代表有N個點.N<=1000000 下面N-1條邊.
Output
輸出你所找到的點,如果具有多個解,請輸出編號最小的那個.
Sample Input
8

1 4

5 6

4 5

6 7

6 8

2 4

3 4
Sample Output
7

題意簡單粗暴
適合本蒟蒻的一道大水題

我們考慮先dfs一遍求出所有節點以1(隨便選)爲根節點的的深度之和。
接着我們考慮根節點從一個點的父親轉移到這個點深度會發生什麼變化?
顯然以這個點爲根的子樹中所有的節點深度減一,其餘節點深度加1
所以我們得到
f[i]=f[fa[i]]-siz[i]+(n-siz[i])
=>f[i]=f[fa[i]]+n-2*siz[i]
所以只要在第一次dfs時順便求出以I爲根節點的子樹的的大小就好

include

include

include

include

include

include

include

include

include

include

using namespace std;
inline int read()
{
char ch=’*’;
int f=1;
while(!isdigit(ch=getchar())) if(ch==’-‘) f=-1;
int num=ch-‘0’;
while(isdigit(ch=getchar())) num=num*10+ch-‘0’;
return num*f;
}
typedef long long ll;
const int maxn = 1000005;
struct edge{
int next,to;
}e[maxn<<1];
int cnt,h[maxn],siz[maxn],fa[maxn],dep[maxn];
long long f[maxn],ans;
int id;
inline void add(int from,int to)
{
e[++cnt].next=h[from];
e[cnt].to=to;
h[from]=cnt;
}
int n,m;
void dfs(int x)
{
siz[x]=1;
for(register int i=h[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x]) continue ;
dep[v]=dep[x]+1;
fa[v]=x;
dfs(v);
siz[x]+=siz[v];
f[x]+=f[v]+siz[v];
}
return ;
}
void dp(int x)
{
if(x!=1)
f[x]=f[fa[x]]+(long long)n-(long long)siz[x]-(long long)siz[x];
for(register int i=h[x];i;i=e[i].next)
if(e[i].to!=fa[x]) dp(e[i].to);
return ;
}

int main()
{
n=read();
int u,v;
for(register int i=1;i

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章