1.只需要求出最大子樹中節點數最小的數目即可
題意:有乙個國王要把他的領土分給兩個兒子,國王的領土是一棵樹,n個結點,n-1條邊把這些結點連起來,現在大小兒子要選擇乙個點作為他的首都,那麼除首都分別是這兩個兒子之外,其他的城市(結點)根據離誰近就歸誰所有,如果一樣遠的話就歸大兒子所有,現在假設兩個人都採取最優策略,且大兒子先選,問大兒子最多能夠得到多少城市?
解法:如果大兒子選擇了乙個點p,那麼這個小兒子選擇的點一定在p點的某個子樹(s)當中,且p的其他子樹一定歸大兒子所有,對於子樹s,小兒子的最優策略顯然是選擇和p相鄰的哪乙個點,否則將損失更多的城市。那麼最後的解法就是大兒子選擇p,p滿足p的最大子樹節點數最少。
設ans是最大子樹節點數,則該題答案為 n-ans
**如下:
//**********
板子//**********
#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;
#define eps 1e-10
#define inf 0x3f3f3f3f
typedef long long ll;
const int maxn = 5e4 + 5;
vectorg[maxn];
int ans, n;
int dfs(int u, int fa)
指標版
int pre,n,dp[maxn];//dp用來裝每個結點的子節點數
int num[maxn],ans,tot;//num用來裝最後的答案
void init()//初始化
void add(int a, int b)//加邊,即建樹
void dfs(int son, int father)//記錄每個結點的子節點數
p = p->next;
} }
void dp_tree(int son, int father)
p = p->next;
} //更新答案
maxx = max(n-dp[son], maxx);
if(maxx < ans)
else if(maxx == ans)
}
int main()
void dfs(int u, int fa)
} }void dp_dfs(int son,int fa)
}//更新答案
maxx = max(n-dp[son], maxx);
if(maxx < ans)
else if(maxx == ans)
}int main()
{ int u,v;
while(scanf("%d",&n)==1)
{ init();for(int i=1;i
POJ 1655 樹的重心(樹形 DP)
balancing act 定義乙個點的 平衡 值等於將這個點拆去後,形成的子樹中節點數的最大值。求一棵樹 平衡 值最小的點。這其實就是樹的重心的概念,通過樹形 dp 很容易解決。當去掉抹一點後,它下面的子樹的節點個數通過 dfs 可以得到,它上面的子樹的節點個數等於總節點個數減去它本身及其子節點的...
poj1655 樹的重心 樹形dp
樹的重心定義為 找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡.處理處每個節點的孩子有幾個,和樹的大小就好了。include include include include include define inf 99999999 usi...
樹形DP求樹的重心 SGU 134
令乙個點的屬性值為 去除這個點以及與這個點相連的所有邊後得到的連通分量的節點數的最大值。則樹的重心定義為 乙個點,這個點的屬性值在所有點中是最小的。sgu 134 即要找出所有的重心,並且找出重心的屬性值。考慮用樹形dp。dp u 表示割去u點,得到的連通分支的節點數的最大值。tot u 記錄以u為...