您的位置:首页 > 其它

GYM 101102 L.Starry Night(贪心+dfs)

2017-03-17 14:34 357 查看
Description

给出一棵树,问通过删点最多能够把这棵树变成多少个星星,星星就是一个点周围不小于三条链且不能有分叉



Input

第一行一整数T表示用例组数,每组用例首先输入一整数n表示点数,之后n-1行每行两个整数u和v表示树上一条边(1<=n<=1e5)

Output

输出适当删点后最多能够得到多少个星星

Sample Input

1

9

1 2

3 2

5 1

3 7

1 4

3 8

1 6

3 9

Sample Output

2

Solution

贪心,每次从末端删去三叉小星星,对于一个点,打两种标记,第一种是被删掉的标记vis1[i],第二种是作为其某个儿子的一叉的标记vis2[i],任意选点为根开始dfs,统计每个点u(父亲节点为f)没被删掉的儿子节点数目num

1.如果u被打上了vis1的标记就不用管了,因为已经被删除了

2.如果u点被打上了vis2标记,说明其被某些儿子作为一叉了(可能有多个,所以不能在dfs到其儿子打标记时就给答案加上了,而是在这一点加,因为u点只能作为一个儿子的一叉),给答案加一,给f打上vis1的标记表示要删除f才能成全u点作为其某个儿子的一叉

3.如果u点两种标记都没被打

num=2说明u点往下只有两个叉,只能给其父亲f打上vis2的标记表示u点要是想成为一个星星就需要f作为u的一叉

num>2说明u只需要其儿子们作为叉就能形成一个星星,答案加一,给其父亲f打上vis1的标记表示f为了成全其儿子u作为一个星星的中心要被删除掉

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 111111
int T,n,vis1[maxn],vis2[maxn],ans;
vector<int>g[maxn];
void dfs(int u,int f)
{
int num=0;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v==f)continue;
dfs(v,u);
if(!vis1[v])num++;
}
if(!vis1[u])
{
if(vis2[u])ans++,vis1[f]=1;
else if(num>=3)ans++,vis1[f]=1;
else if(num==2)vis2[f]=1;
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)g[i].clear();
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);
}
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
ans=0;
dfs(1,0);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: