Codeforces Round #328 (Div. 2) D. Super M
2015-11-14 20:29
183 查看
Super M ~~
题意: 从一个点出发,必须经过给出的k个点,求最短的路,并且最短路有多条则开始点字典序最小
首先,我们知道从必须经过的点出发总是比从其他点出发要短,再者最好不经过一条边两次,三次以上就没意义了,则我们首先从k个点里选一个点出发(root),则离root最远的点,而且字典序更小的点作为出发点不会是路更长,而如果一定有些点一定要经过父节点则意味着要回到父节点就要每条边经过两次,当然由于我们不需要回到父节点,所以我们减去离根节点最远的点的距离就是最短了,当然最后还要找最小的根节点
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath> using namespace std; const int N=200000; vector <int>G ; int cities ; bool mk ; int dep ; int num ; void dfs(int u,int v) { if(mk[u]) num[u]=1; else num[u]=0; for(int i=0;i<G[u].size();i++){ int vv=G[u][i]; if(vv==v) continue; dep[vv]=dep[u]+1; dfs(vv,u); num[u]+=num[vv]; } } int main() { int n,m; scanf("%d%d",&n,&m); int x,y; for(int i=0;i<n-1;i++){ scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } int st; for(int i=0;i<m;i++){ scanf("%d",&x); cities[i]=x; st=x; mk[x]=1; } dfs(st,0); // for(int i=0;i<m;i++) // printf("%d %d\n",cities[i],dep[cities[i]]); int len=0; for(int i=0;i<m;i++){ x=cities[i]; if(dep[x]>dep[st]){ st=x; } if(dep[x]==dep[st] && st>x){ st=x; } } memset(dep,0,sizeof dep); dfs(st,0); len=0; int res=0; for(int i=1;i<=n;i++){ x=i; //printf("%d\n",num[x]); if(num[x]>0 && m-num[x]>0){ res+=2;} if(mk[x]&&dep[x]>len) len=dep[x]; } for(int i=0;i<m;i++){ x=cities[i]; if(dep[x]==len && x<st) st=x; } printf("%d\n",st); printf("%d\n",res-len); } /* 6 3 1 2 1 4 1 3 2 5 2 6 6 4 3 */
相关文章推荐
- OC协议的应用-代理
- 伪目标
- JavaScript之再谈回调与闭包
- iOS性能优化:Instruments使用实战
- 83 Remove Duplicates from Sorted List
- 时序图学习笔记
- 《大道至简》软件工程
- iOS9的新特性以及适配方案
- 论PHP常见的漏洞
- Educational Codeforces Round 1
- Android Studio编译好的apk放在哪里
- HTML 文本格式化
- 169 Majority Element
- 191 Number of 1 Bits
- 8086内存分段理解
- unity 在移动平台中,文件操作路径详解
- 虚拟串口软件和串口调试助手的简单使用
- Redis常用的命令
- ios开发-单击和双击手势的区分处理
- 数组