博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2067: [Poi2004]SZN
阅读量:4557 次
发布时间:2019-06-08

本文共 2549 字,大约阅读时间需要 8 分钟。

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
2 #include
3 #include
4 #include
5 #include
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
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
>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
>1;62 printf("%d %d\n",ans,calc());63 }64 return 0;65 }

 

转载于:https://www.cnblogs.com/chenyushuo/p/4918834.html

你可能感兴趣的文章
java 调整jvm堆大小上限
查看>>
浏览器全屏之requestFullScreen全屏与F11全屏
查看>>
软件包管理:rpm命令管理-安装升级与卸载
查看>>
旋转图像
查看>>
字符串中的数字(字符串、循环)
查看>>
15.select into
查看>>
缓存-->Java中缓存的原理
查看>>
运行web项目端口占用问题
查看>>
Java Spring-IOC和DI
查看>>
【NOIP1999】【Luogu1015】回文数(高精度,模拟)
查看>>
Linux上安装Python3.5
查看>>
crt安装
查看>>
git切换分支报错:error: pathspec 'origin/XXX' did not match any file(s) known to git
查看>>
c++中static的用法详解
查看>>
转 我修改的注册表,但是程序运行起来,还是记着以前的
查看>>
图片轮播功能
查看>>
第六周小组作业:软件测试和评估
查看>>
linux Cacti监控服务器搭建
查看>>
debian(kali Linux) 安装net Core
查看>>
centos 7防火墙设置
查看>>