bzoj2067: [Poi2004]SZN

Description

String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一些顶点和特定数量的边构成. 每个顶点都可以连向许多的其他顶点.一个图是连通且无环的. 图是由许多的线做成的.一条线是一条连接图中两个顶点之间的路径.由于一些技术原因,两条线之间不能有重叠的部分,要保证图中任意一条边都被且仅被一条线所覆盖.由于一些技术原因,做一个这样的图的模型的费用取决于用了多少条线以及最长的那条的长度. (每条边的长度都为1.),给出对应的图,求出最少能用多少条线以及在用最少线的情况下最长的那根线最短可以为多少.

Input

第一行仅包含一个数n – 顶点的总数, 2 <= n <= 10 000. 顶点从1 到 n进行编号. 接下来的n - 1 行描述这些边, 每行两个数a 和 b, 1 <= a, b <= n, a <> b. 表示顶点a和顶点b之间有一条边.

Output

输出两个数,最少用多少条线以及在用最少线的情况下最长线最短可以为多少.

Sample Input

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

Sample Output

4 2

HINT

考虑从1开始dfs,每次对于子树两个两个合并,多出来的往上合,第一问答案就是1+Σ(deg[x]-1)>>1

第二问答案显然具有可二分性,现在只需要判断答案x合不合法

对于每个点,把它子树所有点向上需要的答案统计出来到list[]中。

如果子树个数是偶数且这个点不是1号点,则额外加一个a[i]=0(因为有可能将一支向上连会更优,例子在后面)

然后对a排序,二分删掉a中的一个元素,从大到小匹配判断是否合法,如果任何方案都不合法,则是不合法的直接退出

如果弄到最后都合法,这个答案就合法,不过要注意判断根的时候如果子树是偶数个不能额外加元素,也不能二分判断,而要直接判断合法性

例子:

19

3 6

11 14

14 19

12 7

8 5

10 4

3 11

7 18

17 2

6 12

3 10

11 1

11 8

9 16

1 9

16 15

15 13

4 17

图:

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 10005
 7 #define inf 1061109567
 8 using namespace std;
 9 char ch;
10 int n,a,b,tot,ans,now[maxn],son[maxn<<1],pre[maxn<<1],deg[maxn],cnt,up[maxn],list[maxn];
11 bool ok;
12 void read(int &x){
13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
14     for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
15     if (ok) x=-x;
16 }
17 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b,deg[a]++;}
18 bool check(int x,int lim){
19     for (int i=1,j=cnt;i<j;i++,j--){
20         if (i==x) i++; if (j==x) j--;
21         if (list[i]+list[j]>lim) return false;
22     }
23     return true;
24 }
25 bool dfs(int u,int fa,int lim){
26     for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
27         if (v!=fa) if (!dfs(v,u,lim)) return false;
28     cnt=0;
29     for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
30         if (v!=fa) list[++cnt]=up[v]+1;
31     if (!cnt) return true;
32     if (u!=1&&!(cnt&1)) list[++cnt]=0;
33     sort(list+1,list+cnt+1);
34     if (u==1&&!(cnt&1)) return check(0,lim);
35     int l=1,r=cnt,m;
36     while (l!=r){
37         m=(l+r)>>1;
38         if (check(m,lim)) r=m; else l=m+1;
39     }
40     if (check(l,lim)) up[u]=list[l];
41     else up[u]=inf;
42     return up[u]<=lim;
43 }
44 int calc(){
45     int l=1,r=n-1,m;
46     while (l<r){
47         m=(l+r)>>1;
48         if (dfs(1,0,m)) r=m;
49         else l=m+1;
50     }
51     return l;
52 }
53 int main(){
54     while (~scanf("%d",&n)){
55         tot=0;
56         memset(now,0,sizeof(now));
57         memset(deg,0,sizeof(deg));
58         memset(up,0,sizeof(up));
59         for (int i=1;i<n;i++) read(a),read(b),put(a,b),put(b,a);
60         ans=1;
61         for (int i=1;i<=n;i++) ans+=(deg[i]-1)>>1;
62         printf("%d %d\n",ans,calc());
63     }
64     return 0;
65 }
时间: 2024-12-16 08:39:06

bzoj2067: [Poi2004]SZN的相关文章

【BZOJ2067】[Poi2004]SZN 二分+树上贪心

[BZOJ2067][Poi2004]SZN Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一些顶点和特定数量的边构成. 每个顶点都可以连向许多的其他顶点.一个图是连通且无环的. 图是由许多的线做成的.一条线是一条连接图中两个顶点之间的路径.由于一些技术原因,两条线之间不能有重叠的部分,要保证图中任意一条边都被且仅被一条线所覆盖.由于一些技术原因,做一个这样的图的模型的费用取决于用了多少条线

bzoj 2067 [Poi2004]SZN——二分+贪心

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2067 最少的线段可以贪心地想出来.(结果还是写错了)就是偶数孩子可以自己配对,奇数孩子要带一个上去:算条数的时候在该条拐弯或截止的时候算,就是每个点的度数减1除以2求和,最后加上1表示根节点. 还以为第二问能贪心做呢.结果WA.奇数孩子带一个最小的上去是不行的:偶数孩子都不带上去也是不行的. 于是二分一下答案.结果WA.偶数孩子带一个尽量小的上去还能贪心,奇数孩子并不是用中间那个孩子与别的

bzoj2073【POI2004】PRZ

2073: [POI2004]PRZ Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 169  Solved: 125 [Submit][Status][Discuss] Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过. 队伍里每个人过桥都需要特

2073: [POI2004]PRZ

2073: [POI2004]PRZ Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 284  Solved: 213[Submit][Status][Discuss] Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过. 队伍里每个人过桥都需要特定的

【POI2004】【Bzoj2069】T2 洞穴

T2 洞穴zaw [问题描述] 在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决定组织办一个'King's of Byteotia Cup' 比赛. 参赛者的目标就是任意选择一条路径进入洞穴并尽快出来即可. 一条路径必须经过除了 1 之外还至少要经过其他一个洞室.一条路径中一个洞不能重复经过(除了 1 以外),类似的一条隧道也不能重复经过. 一个著名的洞穴探险家 Byt

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物品,而且选取的个数最大. 注释:$1\le n \le 10^6$. 想法:显然,和骑士类似的,是一个基环树森林.如果A物品可以控制B物品,那就有B物品向A物品连边.对于每一个基环树,如果这个基环树是树的话显然变成树形dp入门题,暴力树形dp即可.然后对于基环树来讲,我们依然记录环上两点,分别以这两

Bzoj2073 [POI2004] PRZ

Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过. 队伍里每个人过桥都需要特定的时间,当一批队员过桥时时间应该算走得最慢的那一个,每个人也有特定的重量,我们想知道如何分批过桥能使总时间最少. Input 第一行两个数: w – 桥能承受的最大重量(100 <= w <= 400) 和 n –

[BZOJ2072][POI2004] MOS过桥

Description 一个夜晚一些旅行者想要过桥. 他们只有一个火把. 火把的亮光最多允许两个旅行者同时过桥. 没有火把或者多于2个人则不能过桥.每个旅行者过桥都需要特定的时间, 两个旅行者同时过桥时时间应该算较慢的那个. 我们想知道所有旅行者最少要花费多少时间才能全部过桥? Example 假如有4个人. 他们分别需要花费6,7,10,15分钟过桥.下图演示了他们如何使用44分钟全部过桥的,但他们能做得更快么? Input第一行一个数n 表示旅行者的总数, 1 <= n <= 100,00

bzoj 2075: [POI2004]KAG

整天鬼畜题搞搞,感觉药丸…… 这种题出到xjoi模拟题里,太神了…… 这题的核心在于分割Cograph,尝试把Cograph的合成过程给求出来. 我们将这张图中的边为黑边,在这张图的补图中出现的边为白边,则黑边和白边构成了一个完全图. 1.如果当前这张图的黑边是不联通的,那么可以检查所有的黑边构成的联通块是不是Cograph,如果都是Cograph,则原图也为Cograph 2.如果当前这张图的白边是不联通的,那么可以检查所有的白边构成的联通块是不是Cograph,如果都是Cograph,则原图