旅行

来源:互联网 发布:淘宝冷门类目有哪些 编辑:程序博客网 时间:2024/04/27 19:19

旅行
题目描述
小 C 上周末和他可爱的同学小 A 一起去 X 湖玩。

X 湖景区一共有 n 个景点,这些景点由 n-1 条观光道连接着,从每个景点开始都可以通过观光道直接或间接地走到其他所有的景点。小 C 带着小 A 从 1 号景点开始游玩。游览完第一个景点后,先由小 C 决定下一个游览的景点,他们一起走去那个景点玩。接下来,他们轮流决定他们下一步去哪个景点玩。他们不会选择已经走过的景点,因为重复游览一个景点是无趣的。当他们无法选择下一个景点时,他们就结束旅程。

小 C 是好动的男孩纸,所以他希望游览的过程尽量长,也就是走过观光道的长度和最大。而小 A 是文静的女孩纸,她希望游览的过程尽量短。小 A 和小 C 都极度聪明,且他们的目光都足够长远,他们做出的决策都是对自己最优的。由于小 C 在旅游前就仔细研究了 X 湖景区的地图,他可以在旅行开始前就用自己惊人的数学能力推算出他和小 A 旅行的路径长度。

小 C 的梦境是美好的。在他的梦里,他和小 A 又进行了 n-1 次旅行,第 i 次旅行从 i+1 号点开始,每次也是小 C 先决定下一个景点,然后小 A,然后小C……直到旅行结束。现在小 C 希望你对于所有 n 次旅行,求出他和小 A 旅行的路径长度。
输入
第一行一个正整数 n,表示景点的个数。

接下来 n-1 行,每行三个正整数 u,v,c。表示有一条连接 u 和 v 的双向观光道,其长度为 c。
输出
输出一共 N 行,每行一个正整数。第 i 行表示从 i 号点开始旅行他们走过的

路径长度。
样例输入
5
1 2 1
1 3 2
2 4 3
2 5 4
样例输出
4
4
7
6
7
提示

【样例解释】从 1 号景点开始:

若小 C 选择走到 3 号景点,则小 A 无法选择下一个景点,旅行的路径长

度为 2

若小 C 选择走到 2 号景点,则小 A 会在 4 号景点和 5 号景点中选择更近的 4 号点,然后小 C 无法选择下一个景点,旅行结束,旅行的路径长度会是 4

所以小 C 会选择走到 2 号点,最终的路径长度是 4

【数据范围】

对于 20%的数据,N ≤ 15

对于 60%的数据,N ≤ 3000 对于 100%的数据,N ≤ 300000, c[i] ≤ 1e9

来源

h[i].maCi

h[i].miAi


h[i].ma=max(h[v].mi+val[e])

h[i].mi=min(h[v].ma+val[e])

vival[e]i

dpf便

dpO(n)n

O(n2)

dp

O(1)

uvuvuvdp

dpdpvdp

fgO(n)

O(1)O()

#include<iostream>#include<cstdio>using namespace std;#define ll long longint num;struct node{  ll ma,mi;}h[400000],l[400000];ll val[700000],ans[400000];int vet[700000],Next[700000],hed[400000];void add(int u,int v,int z){  ++num;  vet[num]=v;  val[num]=z;  Next[num]=hed[u];  hed[u]=num;}void dfs(int x,int fa){  bool flag=true;  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    flag=false;    int v=vet[i];    dfs(v,x);    h[x].ma=max(h[x].ma,h[v].mi+val[i]);    h[x].mi=min(h[x].mi,h[v].ma+val[i]);  }  if (flag) h[x].mi=0;}void makelmax(int x,int fa){  int v1=0,v2=0;  ll mi1=1ll<<60,mi2=1ll<<60;  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    int v=vet[i];    if (h[v].ma+val[i]<mi1){      v2=v1;      mi2=mi1;      v1=v;      mi1=h[v].ma+val[i];    }else if (h[v].ma+val[i]<mi2){      v2=v;      mi2=h[v].ma+val[i];    }  }  //if (x==1){  // printf("%d %lld\n",v1,mi1);  // printf("%d %lld\n",v2,mi2);  //}  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    int v=vet[i];    if (v!=v1) l[v].ma=min(l[v].ma,mi1+val[i]);else l[v].ma=min(l[v].ma,mi2+val[i]);    l[v].ma=min(l[v].ma,l[x].mi+val[i]);  }}void makelmin(int x,int fa){  int v1=0,v2=0;  ll ma1=0,ma2=0;  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    int v=vet[i];    if (h[v].mi+val[i]>ma1){      v2=v1;      ma2=ma1;      v1=v;      ma1=h[v].mi+val[i];    }else if (h[v].mi+val[i]>ma2){      v2=v;      ma2=h[v].mi+val[i];    }  }  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    int v=vet[i];    if (v!=v1) l[v].mi=max(l[v].mi,ma1+val[i]);else l[v].mi=max(l[v].mi,ma2+val[i]);    l[v].mi=max(l[v].mi,l[x].ma+val[i]);  }}void work(int x,int fa){  makelmax(x,fa);  makelmin(x,fa);  for (int i=hed[x];i!=-1;i=Next[i])  if (vet[i]!=fa){    int v=vet[i];    ans[v]=max(h[v].ma,l[v].ma);    work(v,x);  }}int main(){  int n;  scanf("%d",&n);  num=0;  for (int i=1;i<=n;++i){    hed[i]=-1;    h[i].ma=l[i].mi=0;    h[i].mi=l[i].ma=1ll<<60;  }  for (int i=1;i<n;++i){    int x,y,z;    scanf("%d%d%d",&x,&y,&z);    add(x,y,z);    add(y,x,z);  }  dfs(1,0);  //for (int i=1;i<=n;++i){  //  cout<<i<<"^^^^^^^^^^^^^^"<<h[i].ma<<" "<<h[i].mi<<endl;  //  printf("%d %lld %lld\n",i,h[i].ma,h[i].mi);  //}  ans[1]=h[1].ma;  l[1].ma=0;  l[1].mi=1ll<<60;  work(1,0);  //for (int i=1;i<=n;++i){  //  cout<<i<<"^^^^^^^^^^^^^^"<<h[i].ma<<" "<<h[i].mi<<endl;  //  printf("%d %lld %lld\n",i,l[i].ma,l[i].mi);  //}  for (int i=1;i<=n;++i) printf("%lld\n",ans[i]);  //while (1);  return 0;}
原创粉丝点击