您的位置:首页 > 其它

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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: