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
来源/分类
分析
- 先构造无向图,再dfs;
- dfs时使用有返回值模式,其返回值表示各子树节点数目。
- 删除的点满足 以删除点为根,各子树节点数目不超n/2 且 祖先数目也不超过n/2
- 祖先数目=总节点数目-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; }
以上是关于HNIEOJ 3964: 砍树的主要内容,如果未能解决你的问题,请参考以下文章
ZOJ 3964 Yet Another Game of Stones Nim游戏变种
砍树树的豁口向东,树最后向哪边倒?砍树树的豁口向东,树最后向哪边倒?
ZOJ-3964 Yet Another Game of Stones