BJ 集训测试7 A模型
2018-03-21 15:53
218 查看
http://www.elijahqi.win/archives/2753
题目要求:加最少的边使得一棵树不存在割点
我们可以先考虑如果是割边的话应该怎么做。显然答案下界是 ⌈l/2⌉
⌈l/2⌉
其中 l
l
是树中的叶节点个数。我们可以构造出这样的方案:令叶节点的权值为 1 ,非叶节点的权值为 0 ,求整棵树的带权重心 c
c
。由于重心的每个儿子的子树里都只有不超过 ⌊c/2⌋
⌊c/2⌋
个叶子,我们不难构造出一组方案使得每条边连接的两个叶子都来自于重心的不同儿子的子树。
考虑割点,显然答案下界是 max(max{di−1},⌈l/2⌉)
max(max{di−1},⌈l/2⌉)
,其中 di
di
是点 i
i
的度数。我们可以构造出这样的方案:注意到之前的方案里除了重心之外,每个点都保证了删掉它后,它的所有儿子的子树依然是与重心所在的连通块连通的,固整个图也是连通的。
同样先求重心,每次如果最大子树未连的叶子节点大于1
1
我们就把其中一个叶子与最小子树的一个未连的叶子节点连起来,否则就依次连子树个数−1
−1
条边,可以证明这样连是最优的。
注意连边的时候当最大只为1的时候 不能采取大的和小的连边策略 因为这样的话重心可能被放过所以应该都取出来去临近的互相连
题目要求:加最少的边使得一棵树不存在割点
我们可以先考虑如果是割边的话应该怎么做。显然答案下界是 ⌈l/2⌉
⌈l/2⌉
其中 l
l
是树中的叶节点个数。我们可以构造出这样的方案:令叶节点的权值为 1 ,非叶节点的权值为 0 ,求整棵树的带权重心 c
c
。由于重心的每个儿子的子树里都只有不超过 ⌊c/2⌋
⌊c/2⌋
个叶子,我们不难构造出一组方案使得每条边连接的两个叶子都来自于重心的不同儿子的子树。
考虑割点,显然答案下界是 max(max{di−1},⌈l/2⌉)
max(max{di−1},⌈l/2⌉)
,其中 di
di
是点 i
i
的度数。我们可以构造出这样的方案:注意到之前的方案里除了重心之外,每个点都保证了删掉它后,它的所有儿子的子树依然是与重心所在的连通块连通的,固整个图也是连通的。
同样先求重心,每次如果最大子树未连的叶子节点大于1
1
我们就把其中一个叶子与最小子树的一个未连的叶子节点连起来,否则就依次连子树个数−1
−1
条边,可以证明这样连是最优的。
注意连边的时候当最大只为1的时候 不能采取大的和小的连边策略 因为这样的话重心可能被放过所以应该都取出来去临近的互相连
#include<set> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> #define pa pair<int,int> #define N 550000 #define inf 0x3f3f3f3f using namespace std; inline char gc(){ static char now[1<<16],*S,*T; if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();} while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc(); return x*f; } struct cmp{ inline bool operator()(const pa &a,const pa &b){return a.first>b.first||(a.first==b.first&&a.second<b.second);} }; set<pa,cmp> s;int q ; int n,size ,num,h ,root,f ; vector<pa> ans;vector<int>son ; struct node{ int y,next; }data[N<<1]; inline void dfs(int x,int fa){ bool flag=0;size[x]=0; for (int i=h[x];i;i=data[i].next){ int y=data[i].y;if (y==fa) continue;flag=1;dfs(y,x);size[x]+=size[y]; }if (!flag) size[x]=1; } inline void get_root(int x,int fa){ f[x]=size[1]-size[x]; for (int i=h[x];i;i=data[i].next){ int y=data[i].y;if (y==fa) continue; get_root(y,x);f[x]=max(f[x],size[y]); }if (f[root]>f[x]) root=x; } inline void dfs1(int x,int fa,int id){ bool flag=0; for (int i=h[x];i;i=data[i].next){ int y=data[i].y;if (y==fa) continue; flag=1;dfs1(y,x,id); }if (!flag) son[id].push_back(x); } int main(){ //freopen("t1.in","r",stdin); int T=read(); while(T--){ n=read();num=0;memset(h,0,sizeof(h));ans.clear(); for (int i=1;i<n;++i){ int x=read(),y=read(); data[++num].y=y;data[num].next=h[x];h[x]=num; data[++num].y=x;data[num].next=h[y];h[y]=num; }dfs(1,1);root=0;f[0]=inf;get_root(1,1);int cnt=0; for (int i=h[root];i;i=data[i].next){ int y=data[i].y;son[++cnt].clear();dfs1(y,root,cnt); }int last=0; for (int i=1;i<=cnt;++i) s.insert(make_pair(son[i].size(),i)); while(!s.empty()){ if (s.begin()->first==1){ int tot=0; while(!s.empty()) q[++tot]=s.begin()->second,s.erase(s.begin()); for (int i=1;i<tot;++i){ ans.push_back(make 4000 _pair(son[q[i]].back(),son[q[i+1]].back()));last=son[q[i]].back(); }if (tot==1) ans.push_back(make_pair(last,son[q[1]].back())); break; } int id1=s.begin()->second;s.erase(s.begin());last=son[id1].back(); int id2=s.rbegin()->second;s.erase(--s.end()); ans.push_back(make_pair(son[id1].back(),son[id2].back())); son[id1].pop_back();son[id2].pop_back(); if (son[id1].size())s.insert(make_pair(son[id1].size(),id1)); if (son[id2].size())s.insert(make_pair(son[id2].size(),id2)); }printf("%lld\n",ans.size()); for (int i=0;i<ans.size();++i) printf("%d %d\n",ans[i].first,ans[i].second); } return 0; }
相关文章推荐
- BJ 集训测试12 coin
- BJ 集训测试10 序列
- BJ 集训测试6 求和
- BJ 集训测试14 pow
- BJ 集训测试12 同构
- BJ 集训测试9 Problem C King
- BJ 集训8 测试 B 新访问计划
- BJ 集训测试14 bird
- BJ 集训测试8 Problem C 插线板
- BJ 集训测试13 钢琴
- BJ 集训测试7 Mythological VII
- BJ 集训测试13 平行
- BJ 集训测试9 draw
- BJ 集训测试11 level&& codeforces 700E
- BJ 集训测试10 城市
- BJ 集训测试11 捕鱼
- BJ 集训测试11 flow
- 软件测试:过程模型!
- 软件测试4--测试用例的目标及x模型
- 【集训Day1 测试】奇怪数