树的重心性质:
题解:
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<set>
using namespace std;
#define scd(n) scanf("%d",&n)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);i++)
#define pb push_back
#define lowbit(x) x&(-x)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N = 1e5+10;
const int INF = 0x3f3f3f3f;
const LL inf = 0x3f3f3f3f3f3f3f3f;
LL mod = 998244353;
vector<int>tree[N];
int dp[N]; //dp[u]表示以u为根节点的子树中节点的数量
int res;
int n;
int weight;
void dfs(int u,int fa)
{
int sum=0;
dp[u]=1;
for(auto son:tree[u]){
if(son==fa) continue;
dfs(son,u);
dp[u]+=dp[son];
sum=max(sum,dp[son]);
}
sum=max(sum,n-dp[u]);
if(res>sum){
weight=u; //更新重心
res=sum; //更新节点的最大值
}
}
void solve()
{
scd(n);
res=INF;
rep(i,n-1){
int x,y;
scdd(x,y);
tree[x].pb(y);
tree[y].pb(x);
}
dfs(1,0);
cout << weight << ' ' << res << endl;
}
int main()
{
solve();
return 0;
}
下面是一道模板题
题目链接
机翻:
去年,芝加哥到处都是黑帮斗殴和奇怪的谋杀。警察局长真的厌倦了这些犯罪行为,决定逮捕黑手党头目。
不幸的是,芝加哥黑手党的结构相当复杂。有n个已知的与黑手党有关的人。警方追踪他们的活动已经有一段时间了,知道他们中的一些人在互相通信。根据收集到的数据,警察局长建议黑手党的等级可以被描绘成一棵树。黑手党的头目教父(教父)是树的根,如果某人用树中的一个节点来表示,那么它的直接下属就用该节点的子节点来表示。为了达到阴谋的目的,匪徒们只与他们的直接下属和直接主人沟通。
不幸的是,虽然警察知道黑帮的通讯,但他们不知道谁是通讯高手。因此,他们只有一个无方向的通信树,不知道谁是教父。
基于这一想法,黑手党教父最可能想要控制,警察局长提出了一个建议,教父是这样一个人,在删除它后通信树的大小最大剩余的连接组件是尽可能小。帮助警察找到所有可能的教父,他们会逮捕他们。
题意:就是让你找出树的所有重心
题解:树形dp,不过需要注意的是,开vector会TLE,需要写链式前向星
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<set>
using namespace std;
#define scd(n) scanf("%d",&n)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);i++)
#define pb push_back
#define lowbit(x) x&(-x)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N = 5e4+10;
const int INF = 0x3f3f3f3f;
const LL inf = 0x3f3f3f3f3f3f3f3f;
LL mod = 998244353;
int h[N],e[N<<1],ne[N<<1],idx;
int dp[N]; //dp[u]表示以u为根节点的子树中节点的数量
int res;
int n;
int cnt;
int weight[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa)
{
dp[u]=1;
int sum=0;
for(int i=h[u];i!=-1;i=ne[i]){
int son=e[i];
if(son==fa) continue;
dfs(son,u);
dp[u]+=dp[son];
sum=max(sum,dp[son]);
}
sum=max(sum,n-dp[u]);
if(sum<res){
cnt=0; //这一步很关键,起到更新最小值的作用
weight[cnt++]=u;
res=sum;
}else if(sum==res){
weight[cnt++]=u;
}
/*
另一种写法:
if(sum<=n/2) weight[cnt++]=u;
*/
}
void solve()
{
memset(h,-1,sizeof h);
scd(n);
rep(i,n-1){
int x,y;
scdd(x,y);
add(x,y);
add(y,x);
}
res=INF;
dfs(1,0);
sort(weight,weight+cnt);
for(int i=0;i<cnt;i++) cout << weight[i] << ' ';
}
int main()
{
solve();
return 0;
}