HNIEOJ 3964: 砍树

Posted shenyuling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HNIEOJ 3964: 砍树相关的知识,希望对你有一定的参考价值。

3964: 砍树

时间限制: 1 Sec  内存限制: 128 MB
提交: 16  解决: 4
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

 给出一个树形图(“tree-shaped” network),有N个顶点。如果删除树上某一个顶点,整棵树就会分割成若干个部分。显然,每个部分内部仍保持连通性。

现在问:删除哪个点,使得分割开的每个连通子图中点的数量不超过N/2?如果有很多这样的点,就按升序输出。 
    例如,如下图所示的树形图,砍掉顶点3或者顶点8,分割开的各部分满足条件。 
  

 

输入

 第1行:1个整数N,表示顶点数。顶点编号1-N。    接下来n-1行每行两个整数x,y,表示x到y有一条边。

 

输出

 若干行,每行1个整数,表示一个符合条件的顶点的编号。如果没有顶点符合条件,则仅在第1行输出“NONE”。

 

样例输入

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8

 

样例输出

3
8

 

提示

 

【数据范围及约定】 

对于50%的数据,满足1≤N≤10000 

对于100%的数据,满足1≤N≤1000000 

 

来源/分类

分析

  1. 先构造无向图,再dfs;
  2. dfs时使用有返回值模式,其返回值表示各子树节点数目。
  3. 删除的点满足   以删除点为根,各子树节点数目不超n/2  且  祖先数目也不超过n/2
  4. 祖先数目=总节点数目-1-各子树节点数目
代码如下
技术分享图片
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 1000000+4
typedef struct anode
{
    int adjvex;
    struct anode *nextarc;
}arcnode;
typedef struct
{
    arcnode *firstarc;
}vnode;
typedef struct
{
    vnode adjlist[maxn];
    int n,e;
}adjgraph;
int visit[maxn],ans[maxn],n;
int dfs(adjgraph *g,int v)
{
    int max=0,h=0,flag=0;
    visit[v]++;
    arcnode *p=g->adjlist[v].firstarc;
    while(p!=NULL)
    {
        
        if(!visit[p->adjvex]) 
        {
            int temp=dfs(g,p->adjvex);
            h+=temp;//所以孩子数目 
            max>temp? : max=temp; //从分枝中找出最大节点数
        }
        p=p->nextarc;
    }
    ans[v]= max>n-1-h ? max:n-1-h;  
    return h+1;
}
void link(adjgraph *&g,int a,int b)
{
    arcnode *p1=g->adjlist[a-1].firstarc,*p;
    p=(arcnode *)malloc(sizeof(arcnode));
    p->adjvex=b-1;
    p->nextarc=NULL;
    if(p1==NULL)
        g->adjlist[a-1].firstarc=p;
    else
    {
        p->nextarc=p1->nextarc;
        p1->nextarc=p;
    }
}
void destroy(adjgraph *&g)
{
    arcnode *p;
    for(int i=0;i<g->n;i++)
    {
        p=g->adjlist[i].firstarc;
        while(p!=NULL)
        {
            arcnode *temp=p;
            p=p->nextarc;
            free(temp);
        }
    }
    free(g); 
}
int main()
{
    int i,flag1=1;
    adjgraph *g;
    g=(adjgraph *)malloc(sizeof(adjgraph));
    scanf("%d",&n);
    g->n=n;
    for(i=0;i<n;i++)
        g->adjlist[i].firstarc=NULL;
    for(i=0;i<n-1;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        link(g,a,b);
        link(g,b,a);
    }
    /*for(i=0;i<n;i++)
    {
        arcnode *p;
        p=g->adjlist[i].firstarc;
        printf("%d->",i+1);
        while(p!=NULL)
        {
            printf("%d->",p->adjvex+1);
            p=p->nextarc;
        }
        printf("NULL
");
    }*/
    dfs(g,0);
    int flag=0;
    for(i=0;i<n;i++)
        if(ans[i]<=(n>>1))
        {
           printf("%d
",i+1);
           flag=1;
        }
    if(!flag)
       printf("NONE
");
    destroy(g);
    return 0;
}
View Code

 

以上是关于HNIEOJ 3964: 砍树的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ 3964 Yet Another Game of Stones Nim游戏变种

砍树树的豁口向东,树最后向哪边倒?砍树树的豁口向东,树最后向哪边倒?

ZOJ-3964 Yet Another Game of Stones

LuoguP3964 [TJOI2013]松鼠聚会切比雪夫距离/前缀和

1369 xth 砍树

codevs1369 xth 砍树(线段树)