传送门

文章目录

  • 题意:
  • 思路:

题意:

给你一颗树,但是这棵树的边是双向的,且花费为1。对于每个点,可以在连向他的边中选择一条,使由这个点到边的另一个点的有向边花费变成1,对于每个点都可以这样选择一条由他出去的有向边使其花费为1,要求最小化每两个点之间的最大值。

思路:

由于不会证明我的思路,以后想明白了再说,所以只说一下做法吧。
先找到这棵树直径的中心位置,这个可以用dfs找路径的方式轻松找到,让后以这个点为根,做一棵内向树,让每个点的边都连向其父节点,那么最大值就是以中心为根的树的最大深度。这个时候并没有结束,最后你会发现根节点还没用到考虑什么时候根节点连出去的边能使最大值变小呢?如果我们树的最大深度是mxmxmx,且有两个子树的最大深度都是这个,那么我们不管加到哪里都不会改变最大值。否则的话如果只有一个,我们可以将根与这颗子树连一条边,这样最大深度就可以减一。让后就是实现的时候注意一下细节就好啦。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,M=N*2,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,root;
map<PII,int>mp;
vector<int>v[N];
int ans[N],d[N];
int e[M],ne[M],h[N],w[M],idx;
int depth[N],res;
bool st[N];
int ed,flag,pre[N];void add(int a,int b,int c)
{e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}void dfs_dep(int u,int fa)
{depth[u]=depth[fa]+1;for(auto x:v[u]){int ver=x;if(ver==fa) continue;dfs_dep(ver,u);}
}void dfs(int u,int fa)
{if(flag) return;if(u==ed) { flag=1; return; }for(auto x:v[u]){if(x==fa) continue;pre[x]=u;dfs(x,u);if(flag) return;pre[x]=0;}
}void dfs_add(int u,int fa)
{for(auto x:v[u]){if(x==fa) continue;ans[x]=mp[{x,u}];dfs_add(x,u);}
}void dfs_d(int u,int fa)
{int mx=0;for(auto x:v[u]){if(x==fa) continue;dfs_d(x,u);mx=max(mx,depth[x]+1);}depth[u]=mx;
}int main()
{//  ios::sync_with_stdio(false);
//  cin.tie(0);memset(h,-1,sizeof(h));scanf("%d",&n);for(int i=1;i<=n-1;i++){int a,b; scanf("%d%d",&a,&b);v[a].pb(b),v[b].pb(a);mp[{a,b}]=i; mp[{b,a}]=i;}dfs_dep(1,0);int id=0,mx=-1;for(int i=1;i<=n;i++) if(depth[i]>mx) mx=depth[i],root=i;memset(depth,0,sizeof(depth));dfs_dep(root,0); mx=-1;for(int i=1;i<=n;i++) if(depth[i]>mx) mx=depth[i],ed=i;dfs(root,0);vector<int>v; v.pb(ed);pre[root]=0;while(pre[ed]!=0) v.pb(pre[ed]),ed=pre[ed];root=v[v.size()/2];dfs_add(root,0); memset(depth,0,sizeof(depth));dfs_d(root,0);vector<int>vv;mx=-1;for(int i=1;i<=n;i++) if(i!=root) mx=max(mx,depth[i]);for(int i=1;i<=n;i++) if(depth[i]==mx&&i!=root) vv.pb(i);ans[root]=mp[{root,vv[0]}];mx++;if(vv.size()>1) res=mx;else res=mx-1;printf("%d\n",res);for(int i=1;i<=n;i++) printf("%d ",ans[i]);puts("");return 0;
}
/**/

ICPC Trainings Moscow2020 K. King and Zeroing 树直径 + 思维相关推荐

  1. 置换 ---- 2020-2021 ICPC NERC 的 K. King‘s Task[置换类型思维题]

    题目链接 题目大意: 就是给你一个长度为2∗n2*n2∗n的全排列,有两种操作 1.就是每次交换p1andp2,p3andp4....p_1\; and\;p_2,p_3\;and\;p_4....p ...

  2. 2018-2019 ICPC, NEERC, Northern Eurasia Finals K. King Kog's Reception 线段树

    K. King Kog's Reception 题意:有q个操作,第 i 次操作若为 + t d,表示在 t 这个时刻插入一个耗时为 d 的骑士,若 -  i 表示删除第 i 个操作,若 ? t 表示 ...

  3. [NBUT 1458 Teemo]区间第k大问题,划分树

    裸的区间第k大问题,划分树搞起. #pragma comment(linker, "/STACK:10240000") #include <map> #include ...

  4. 【2021牛客暑期多校训练营5】K King of Range(单调队列)

    K King of Range 题意: 给出一个长为n的序列,m次操作,每次操作求对于一个指定的k,原序列存在多少个连续子序列,满足该区间内最大值减最小值严格大于k. 思路: 令 Ri 为 l=i 时 ...

  5. HDU 4607 Park Visit 两次DFS求树直径

    两次DFS求树直径方法见 这里. 这里的直径是指最长链包含的节点个数,而上一题是指最长链的路径权值之和,注意区分. K <= R: ans = K − 1; K > R:   ans = ...

  6. hdu4514 并查集+树直径

    这道题题目就是说给你一个图,然后判断能不能成环,不能成环就输出最长的那一条路. 首先分析问题.怎么判断环?这是图中一个很常见的问题,在无向图中判环我们可以用并查集,在有向图中可以使用tarjan或者拓 ...

  7. A. Lightning Routing I 线段树维护树直径

    A. Lightning Routing I 题意:带修改的边权树,查询给定点到任意点的最远距离. 题解:首先我们树直径的合并,两颗子树合并后,新的树直径端点在原理两颗子树的树直径端点产生.那么我们就 ...

  8. Mindmanager2020教程篇画一个树状思维导图及试用密钥过期

    MindManager思维导图是一个创造.管理和交流思想的通用标准,其可视化的绘图软件有着直观.友好的用户界面和丰富的功能,这将帮助您有序地组织您的思维.资源和项目进程. 在分析问题时,有许多可行的分 ...

  9. Rikka with Travels 动态维护树直径

    Rikka with Travels 题意:求两条不相交的路线长度的有序对数. 题解:暴力枚举每条边对应两个点对应子树的树直径. 注意:不要用倍增求lca,不然时间会挂,要用树剖求. #include ...

最新文章

  1. 亲历惊心48小时抢救35亿交易数据
  2. 着手一个手游项目的思考
  3. tfs 点获取最新,如果检查到大量冲突
  4. TensorRT trtexec的用法
  5. mysql 拼音查询_mysql实现用拼音搜索中文的数据库实现
  6. 算法和编程面试题精选 TOP50!(附代码+解题思路+答案)
  7. SAP Spartacus Org Unit明细页面的设计原理
  8. python的代码复用技术_Python__函数和代码复用
  9. 2019,转行人工智能?机会来了!
  10. 《代码敲不队》第三次作业:团队项目的原型设计
  11. 一个小小的抽奖活动测试脚本(python2.7)
  12. 浏览器从输入到输出的过程与原理一
  13. 网页源代码怎么屏蔽?
  14. diskgenius扩容c盘重启电脑卡住_无损扩容分区
  15. C语言半框,如何挑选适合自己的镜框(镜片)?
  16. 作为面试官,我是如何甄别应聘者的包装程度
  17. vue-cli 项目启动输出 INFO Starting development server... 69o/o after emitting CopyPlugin
  18. 过程与结果——独立思考——认真详谈
  19. 励志短片:献给努力前行的你
  20. python屏幕录制与回放_使用Python来做一个屏幕录制工具的操作代码

热门文章

  1. 神奇又好玩的谢尔宾斯基雪花!
  2. 有图有真相!这世界上,竟有人跟你长得一模一样!
  3. get到一个生气后的牵手方式!太可爱了
  4. 数学特级教师:数学除了做习题,我还他让他们看这十部纪录片!
  5. 10G 职场晋升/IT干货/生活技能/理财秘籍 【全套】学习资料免费送!
  6. 多个php一个机器,如何利用docker在同一台机器上搭建多套php开发环境?
  7. 在安卓上安装java_如何在Android上安装JavaCV并使用FrameGrabber
  8. java mongodb 批量删除_MONGODB删除/新增/更改大量记录的方法
  9. eeprom stm8l 擦除 读写_[STM8L]EEPROM操作读与写
  10. 后端返回number类型数据_Javascript基础教程之数据类型 (数值 Number)