【XSY2785】模型
题目描述
给你一棵\(n\)个点的树,让你加最少的边,使得图中没有割点。
要求输出方案。
\(n\leq 500000\)
题解
把叶子的权值设为\(1\),其他点设为\(0\),找出带权重心。
以重心为根DFS,算出每棵子树的叶子节点个数。
设有\(l\)个叶子节点。易证每棵子树叶子节点个数不会超过\(\lfloor\frac{l}{2}\rfloor\)。
把子树按叶子节点个数从大到小排序,从第二大的子树开始,每棵子树选一个叶子和前面剩余最多叶子的子树中选一个叶子连一条边。
易证这样操作完后重心就不是割点,且剩余叶子最多的子树叶子不会超过总剩余叶子个数\(\div 2\)(向上取整)。
证明的话,显然次大叶子个数$\geq \(最大叶子个数\)-1$。
然后就每次选两个剩余叶子个数最多的子树连起来就好了。
时间复杂度:可以做到\(O(n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<utility>
#include<vector>
#include<queue>
using namespace std;
typedef pair<int,int> pii;
struct graph
{
int v[1000010];
int t[1000010];
int h[500010];
int n;
graph()
{
memset(h,0,sizeof h);
n=0;
}
void clear(int x)
{
for(int i=1;i<=x;i++)
h[i]=0;
n=0;
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
graph g;
int s[500010];
int f[500010];
int d[500010];
int rt,rtsz;
int tot;
vector<int> b[500010];
int h[500010];
void dfs(int x,int fa)
{
f[x]=fa;
s[x]=0;
if(d[x]==1)
s[x]++;
for(int i=g.h[x];i;i=g.t[i])
if(g.v[i]!=fa)
{
dfs(g.v[i],x);
s[x]+=s[g.v[i]];
}
}
void dfs2(int x)
{
int mx=0;
for(int i=g.h[x];i;i=g.t[i])
if(g.v[i]!=f[x])
{
mx=max(mx,s[g.v[i]]);
dfs2(g.v[i]);
}
mx=max(mx,tot-s[x]);
if(d[x]>1)
{
if(mx<rtsz)
{
rtsz=mx;
rt=x;
}
}
}
void dfs(int x,int fa,int y)
{
if(d[x]==1)
b[y].push_back(x);
else
for(int i=g.h[x];i;i=g.t[i])
if(g.v[i]!=fa)
dfs(g.v[i],x,y);
}
int e[500010];
int cmp(int x,int y)
{
return b[x].size()>b[y].size();
}
vector<int> c[500010];
int ans[500010][2];
priority_queue<pii> q;
void solve()
{
int n;
scanf("%d",&n);
g.clear(n);
for(int i=1;i<=n;i++)
d[i]=0;
for(int i=1;i<=n;i++)
b[i].clear();
for(int i=1;i<=n;i++)
c[i].clear();
int cnt=0;
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
d[x]++;
d[y]++;
g.add(x,y);
g.add(y,x);
}
dfs(1,0);
tot=s[1];
rtsz=0x7fffffff;
dfs2(1);
int t=0;
for(int i=g.h[rt];i;i=g.t[i])
{
dfs(g.v[i],rt,g.v[i]);
e[++t]=g.v[i];
}
sort(e+1,e+t+1,cmp);
for(int i=1;i<=t;i++)
h[i]=b[e[i]].back();
c[b[e[1]].size()].push_back(1);
int now=b[e[1]].size();
for(int i=2;i<=t;i++)
{
while(!c[now].size())
now--;
int y=c[now].back();
c[now].pop_back();
ans[++cnt][0]=b[e[i]].back();
if(b[e[i]].size()>=1)
b[e[i]].pop_back();
c[b[e[i]].size()].push_back(i);
if(b[e[y]].size()==0)
ans[cnt][1]=h[y];
else
ans[cnt][1]=b[e[y]].back();
if(b[e[y]].size()>=1)
b[e[y]].pop_back();
now=max(now,(int)b[e[i]].size());
c[b[e[y]].size()].push_back(y);
if(ans[cnt][0]==ans[cnt][1])
printf("1\n");
}
while(!q.empty())
q.pop();
for(int i=1;i<=t;i++)
if(b[e[i]].size())
q.push(pii(b[e[i]].size(),i));
while(!q.empty()&&q.top().first>=1)
{
pii x=q.top(),y;
q.pop();
if(!q.empty()&&q.top().first>=1)
{
y=q.top();
q.pop();
}
else
if(x.second==1)
y=pii(0,2);
else
y=pii(0,1);
ans[++cnt][0]=b[e[x.second]].back();
b[e[x.second]].pop_back();
if(b[e[y.second]].size()==0)
ans[cnt][1]=h[y.second];
else
{
ans[cnt][1]=b[e[y.second]].back();
b[e[y.second]].pop_back();
}
x.first--;
y.first--;
if(x.first>0)
q.push(x);
if(y.first>0)
q.push(y);
if(ans[cnt][0]==ans[cnt][1])
printf("2\n");
}
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
printf("%d %d\n",ans[i][0],ans[i][1]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}
【XSY2785】模型的更多相关文章
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
- ASP.NET Core MVC/WebAPi 模型绑定探索
前言 相信一直关注我的园友都知道,我写的博文都没有特别枯燥理论性的东西,主要是当每开启一门新的技术之旅时,刚开始就直接去看底层实现原理,第一会感觉索然无味,第二也不明白到底为何要这样做,所以只有当你用 ...
- ASP.NET路由模型解析
大家好,我又来吹牛逼了 ~-_-~ 转载请注明出处:来自吹牛逼之<ASP.NET路由模型解析> 背景:很多人知道Asp.Net中路由怎么用的,却不知道路由模型内部的运行原理,今天我就给大家 ...
- 高性能IO模型浅析
高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking ...
- 探索ASP.NET MVC5系列之~~~4.模型篇---包含模型常用特性和过度提交防御
其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...
- 隐马尔科夫模型python实现简单拼音输入法
在网上看到一篇关于隐马尔科夫模型的介绍,觉得简直不能再神奇,又在网上找到大神的一篇关于如何用隐马尔可夫模型实现中文拼音输入的博客,无奈大神没给可以运行的代码,只能纯手动网上找到了结巴分词的词库,根据此 ...
- webapi - 模型验证
本次要和大家分享的是webapi的模型验证,讲解的内容可能不单单是做验证,但都是围绕模型来说明的:首先来吐槽下,今天下午老板为自己买了套新办公家具,看起来挺好说明老板有钱,不好的是我们干技术的又成了搬 ...
- 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 【NLP】蓦然回首:谈谈学习模型的评估系列文章(一)
统计角度窥视模型概念 作者:白宁超 2016年7月18日17:18:43 摘要:写本文的初衷源于基于HMM模型序列标注的一个实验,实验完成之后,迫切想知道采用的序列标注模型的好坏,有哪些指标可以度量. ...
随机推荐
- 小P的秘籍
题目描述 小P马上就要来到程序设计大赛的现场.上了,他希望能够AK这次比赛,所以他找到了一个字符串. 这个字符串长度为n,由A和K组成.这个字符串被小p称为AK串.小P任意截取一个区间s,使得这个区间 ...
- Divisors of Two Integers CodeForces - 1108B (数学+思维)
Recently you have received two positive integer numbers xx and yy. You forgot them, but you remember ...
- (关于数据传输安全)SSH协议
这里说的不是java的SSH框架,是1995年,芬兰学者Tatu Ylonen设计的SSH协议. 有计算机网络基础的同学都知道,在网上传输的数据是可以被截取的.那么怎样才能获得安全? 一.春点行话 电 ...
- echarts使用笔记三:柱子对比
app.title = '坐标轴刻度与标签对齐'; option = { title : { //标题 x : 'center', y : 5, text : '对比图' //换行用 \n }, le ...
- Redis启动及密码修改
.cmd启动Redis: redis-server.exe redis.windows.conf #注意指定配置文件来启动 .cmd登陆redis redis-cli.exe -h -a .修改密码 ...
- PAT L3-016 二叉搜索树的结构
https://pintia.cn/problem-sets/994805046380707840/problems/994805047903240192 二叉搜索树或者是一棵空树,或者是具有下列性质 ...
- PAT L3-007 天梯地图
https://pintia.cn/problem-sets/994805046380707840/problems/994805051153825792 本题要求你实现一个天梯赛专属在线地图,队员输 ...
- select into赋值方式
declare v_price ,);--单价 v_usenum number;--水费字数 v_usenum2 number;--使用吨数 begin v_price:=2.45;--每吨单价 -- ...
- bootstrap模态框modal使用remote动态加载内容,第二次加载显示相同内容解决办法
bootstrap的modal中,使用remote可以动态加载页面到modal-body中,并弹窗显示 如果提供的是 URL,将利用 jQuery 的 load 方法从此 URL 地址加载要展示的内容 ...
- 模态框 modal data-toggle data-target
模态框 modal data-toggle data-target 1. Data-*属性 模态框(modal) 触发事件(data-toggle) 触发对象data-target(ID 或类) ...